【译】迁移到Room的7个步骤

译自7 Steps To Room

Room 是一个持久化的库,是 Android Architecture Components 的一部分。使用 Room 可以更容易的处理 app 中的 SQLiteDatabase 对象,减少模板代码的数量以及在编译时验证 SQL 查询语句。

下面是在 app 中使用 Room 的七个基本步骤:

  1. 更新项目下的 build.gradle 依赖

    allprojects {
    	repositories {
    		google ()
    		jcenter ()
    	}
    }
    复制代码

    在同文件(也可能是 versions.gradle)下配置 roomVersion

    ext {
    	…
    	roomVersion = '…'
    }
    复制代码

    app/build.gradle 中添加 Room 的依赖

    dependence {
    	…
    	implementation "android.arch.persistence.room:runtime:$rootProject.roomVersion"
    	annotationProcessor "android.arch.persistence.room:compiler:$rootProject.roomVersion"
    	androidTestimplementation "android.arch.persistence.room:testing:$rootProject.roomVersion"
    }
    复制代码

    对于从 SQLiteDatabaseHelper 迁移到 Room 的,需要实现一个 Migration 类来保持 user 数据需要升级数据库的版本号。需要调整架构来测试这个迁移。为此需要在 app/build.gradle 添加如下代码:

    android {
        defaultConfig {
            ...
            //用于 Room 的迁移测试
            javaCompileOptions {
                annotationProcessorOptions {
                    arguments = ["room.schemaLocations": "$projectDir/schemas".toString()]
                }
            }
        }
        //用于 Room 的迁移测试
        sourceSets {
            androidTest.assets.srcDirs += files("$projectDir/schemas".toString())
        }
    }
    复制代码
  2. 将 model 类更新为 entity

    • 使用@Entity标注这个类,并将表名设置给tableName属性;
    • 给主键对应的字段添加@PrimaryKey注解
    • 给字段设置@ColumnInfo(name = "column_name")注解
    • 如果有多个构造函数可用,添加@Ignore注解告诉 Room 哪个要用,哪个不要。
    @Entity(tableName = "Users")
    public class User {
        @PrimaryKey
        @ColumnInfo(name = "userid")
        private String mId;
    
        @ColumnInfo(name = "username")
        private String mUserName;
    
        @ColumnInfo(name = "last_update")
        private Date mDate;
    
        @Ignore
        public User(String userName) {
            mId = UUID.randomUUID().toString();
            mUserName = userName;
            mDate = new Date(System.currentTimeMillis());
        }
    
        public User(String id, String userName, Date date) {
            this.mId = id;
            this.mUserName = userName;
            this.mDate = date;
        }
        ...
    }
    复制代码
  3. 创建数据访问对象Data Access Objects(DAOs)

    DAOs负责定义访问数据库的方法。在项目的初始化 SQLite 实现中,所有的数据库查询都在LocalUserDataSource中使用Cursor对象完成。使用 Room,不需要关联代码所有的Cursor并且在UserDao类中使用注解简单定义了查询操作。

    例如,需要查询数据库中的所有用户时,我们只需要写如下代码,Room 就会处理所有这些繁重的任务。

    @Query("SELECT * FROM Users")
    List<User> getUsers();
    复制代码
  4. 创建数据库

    到目前为止,已经定义了Users表,和它相关的查询操作,但还没有创建将其他 Room 组件组合在一起的数据库。为了实现这一点,我们需要定义一个继承了RoomDatabase的抽象类。这个类用@Database注解修饰,列举了包含在数据库中的 entity 以及操作他们的 DAO。

    @Database(entities = {User.class}, version = 2)
    @TypeConverters(DataConverter.class)
    public abstract class UserDatabase extends RoomDatabase {
        
        private static UsersDatabase INSTANCE;
        
        public abstract UserDao userDao();
    复制代码

    如果是从版本1迁移到2,那么需要实现一个Migration类告诉 Room 迁移时需要做什么。这里得数据库架构没有发生变化,所以只需要一个空实现即可。

        static final Migration MIGRATION_1_2 = new Migration(1, 2) {
            @Override
            public void migration(SupportSQLiteDatabase database) {
                //数据库无修改,空实现
            }
        };
    复制代码

    UsersDatabase类中创建数据库对象,定义数据库的名称和迁移

        database = Room.databaseBuilder(context.getApplicationContext(),
                UsersDatabse.class, "Sample.db")
                .addMigrations(MIGRATION_1_2)
                .build();
    }
    复制代码

    更多关于数据库迁移是如何实现的以及底层是如何运行得,请参见下文的文章:

  5. 在这一步,将修改LocalUserDatabaseSource类来使用UserDao的方法。为了做到这一点,首先要通过移除Context,添加UserDao来修改构造函数。当然,其他实例化LocalUserDatabaseSource的类也需要修改。然后,调用UserDao的方法更新LocalDatabaseSource的查询数据库的方法。

        public List<User> getUsers() {
            return mUserDao.getUsers();
        }
    复制代码

    运行代码!Room 的一个非常棒的特性就是,如果你的数据库操作在主线程执行,你的 app 会崩溃,会显示下面的异常信息:

    java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
    复制代码
  6. 上机实测

    现在测试创建的UserDaoUsersDatabaseLocalUserDatabaseSource

    测试UserDao

    创建一个AndroidJUnit4测试类用于测试UserDao。Room 的一个很棒的特性就是可以在内存中创建数据库,避免需要清除每次的测试用例。

      @Before
      public void initDb() throws Exception {
          mDatabse = Room.inMemoryDatabaseBuilder(
                                InstrumentationRegistry.getContext(),
                                UsersDatabse.class)
                         .build();
      }
    复制代码

    确保每次测试后关闭了数据库连接

      @After
      public void closeDb() throws Exception {
          mDatabase.close();
      }
    复制代码

    为了测试插入一个User,例如,可以先插入这个对象,再检查能否从数据库中得到这个对象。

      @Test
      public void insertAndGetUser() {
          // When inserting a new user in the data source
          mDatabase.userDao().insertUser(USER);
    
          //The user can be retrieved
          List<User> users = mDatabase.userDao().getUsers();
          assertThat(users.size(), is(1));
          User dbUser = users.get(0);
          assertEquals(dbUser.getId(), USER.getId());
          assertEquals(dbUser.getUserName(), USER.getUserName());
      }
    复制代码

    测试LocalUserDataSource中的UserDao使用 我们需要做的是创建一个内存中的数据库,并从中获取一个UserDao,并将其作为LocalUserDataSource构造函数的参数。

      @Before
      public void initDb() throws Exception {
          mDatabase = Room.inMemoryDatabaseBuilder(
                         InstrumentationRegistry.getContext(),
                         UsersDatabase.class)
                  .build();
          mDataSource = new LocalUserDataSource(mDatabase.userDao());
      }
    复制代码

    MigrationTsetHelper如何使用,请参见下面的博客文章:

  7. 删除UserDbHelper

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值