[译] Room ???? Coroutines

栏目: 数据库 · 发布时间: 5年前

内容简介:Room 2.1(目前为 alpha 版本)添加了对 Kotlin 协程的支持。DAO 方法现在可以被标记为挂起以确保他们不会在主线程执行。默认情况下,Room 会使用架构组件 I/O目前,Coroutines 对 Room 的支持正在大力开发中,该库的未来版本中将会增加更多的特性。为了在你的 app 中使用协程和 Room,需将 Room 升级为 2.1 版本并在
[译] Room ???? Coroutines

Room 2.1(目前为 alpha 版本)添加了对 Kotlin 协程的支持。DAO 方法现在可以被标记为挂起以确保他们不会在主线程执行。默认情况下,Room 会使用架构组件 I/O Executor 作为 Dispatcher 来执行 SQL 语句,但在构建 RoomDatabase 的时候你也可以提供自己的 Executor 。请继续阅读以了解如何使用它、引擎内部的工作原理以及如何测试该项新功能。

目前,Coroutines 对 Room 的支持正在大力开发中,该库的未来版本中将会增加更多的特性。

给你的数据库添加 suspense 特性

为了在你的 app 中使用协程和 Room,需将 Room 升级为 2.1 版本并在 build.gradle 文件中添加新的依赖:

implementation "androidx.room:room-coroutines:${versions.room}"
复制代码

你还需要 Kotlin 1.3.0 和Coroutines 1.0.0 及以上版本。

现在,你可以更新 DAO 方法来使用挂起函数了:

@Dao
interface UsersDao {

    @Query("SELECT * FROM users")
    suspend fun getUsers(): List<User>

    @Query("UPDATE users SET age = age + 1 WHERE userId = :userId")
    suspend fun incrementUserAge(userId: String)

    @Insert
    suspend fun insertUser(user: User)

    @Update
    suspend fun updateUser(user: User)

    @Delete
    suspend fun deleteUser(user: User)

}
复制代码

具有 suspend 方法的 DAO

@Transaction 方法也可以挂起,并且可以调用其他挂起的 DAO 方法:

@Dao
abstract class UsersDao {
    
    @Transaction
    open suspend fun setLoggedInUser(loggedInUser: User) {
        deleteUser(loggedInUser)
        insertUser(loggedInUser)
    }

    @Query("DELETE FROM users")
    abstract fun deleteUser(user: User)

    @Insert
    abstract suspend fun insertUser(user: User)
}
复制代码

具有挂起事务功能的 DAO

Room 会根据是否在事务内调用挂起方法进行区别对待:

1. 事务内

Room 不会对触发数据库语句的协程上下文(CoroutineContext)做任何处理。方法调用者有责任确保当前不是在 UI 线程。由于 suspend 方法只能在其他 suspend 方法或协程中调用,因此需确保你使用的 Dispatcher Dispatchers.IO 或自定义的,而不是 Dispatcher.Main

2. 事务外

Room 会确保数据库语句是在架构组件 I/O Dispatcher 上被触发。该 Dispatcher 是基于使处于后台工作的 LiveData 运行起来的同一 I/O Executor 而创建的。

测试 DAO 挂起方法

测试 DAO 的挂起方法与测试其他挂起方法一般无二。例如,为了测试在插入一个用户后我们还可以取到它,我们将测试代码包含在一个 runBlocking 代码块中:

@Test fun insertAndGetUser() = runBlocking {
    // Given a User that has been inserted into the DB
    userDao.insertUser(user)

    // When getting the Users via the DAO
    val usersFromDb = userDao.getUsers()

    // Then the retrieved Users matches the original user object
    assertEquals(listOf(user), userFromDb)
}
复制代码

测试 DAO 的挂起方法

原理

为了能够了解原理,让我们看一下 Room 为同步的和挂起的插入方法生成的 DAO 实现类:

@Insert
fun insertUserSync(user: User)

@Insert
suspend fun insertUser(user: User)
复制代码

同步的和挂起的插入方法

对于同步插入而言,生成的代码开启了一个事务,执行插入操作,将事务标记为成功并结束。同步方法只会在调用它的线程中执行插入操作。

@Override
public void insertUserSync(final User user) {
  __db.beginTransaction();
  try {
    __insertionAdapterOfUser.insert(user);
    __db.setTransactionSuccessful();
  } finally {
    __db.endTransaction();
  }
}
复制代码

Room 对同步插入生成的实现代码

再看一下添加 suspend 修饰符后发生的变化:生成的代码会确保数据在非 UI 线程上被插入。

生成的代码传入了一个 continution 和待插入的数据。使用了和同步插入方法相同的逻辑,不同的是它在一个 Callable#call 方法中执行。

@Override
public Object insertUserSuspend(final User user,
    final Continuation<? super Unit> p1) {
  return CoroutinesRoom.execute(__db, new Callable<Unit>() {
    @Override
    public Unit call() throws Exception {
      __db.beginTransaction();
      try {
        __insertionAdapterOfUser.insert(user);
        __db.setTransactionSuccessful();
        return kotlin.Unit.INSTANCE;
      } finally {
        __db.endTransaction();
      }
    }
  }, p1);
}
复制代码

Room 对挂起插入生成的实现代码

不过有趣的是 CoroutinesRoom.execute 方法,这是一个根据数据库是否打开以及是否处于事务内来处理上下文切换的方法。

情形 1. 数据库被打开同时处于事务内

这种情况下只触发了 call 方法,即用户在数据库中的实际插入操作

情形 2. 非事务

Room 通过架构组件 IO Executor 来确保 Callable#call 中的操作是在后台线程中完成的。

suspend fun <R> execute(db: RoomDatabase, callable: Callable<R>): R {
   if (db.isOpen && db.inTransaction()) {
       return callable.call()
   }
   return withContext(db.queryExecutor.asCoroutineDispatcher()) {
       callable.call()
   }
}
复制代码

CoroutinesRoom.execute 实现

现在就开始在你的 app 中使用 Room 和协程吧,保证数据库的操作在一个非 UI 分发器上执行。在 DAO 方法上添加 suspend 修饰符并在其他 supend 方法或者协程中调用。

感谢Chris Banes 和Jose Alcérreca。

如果发现译文存在错误或其他需要改进的地方,欢迎到 掘金翻译计划 对译文进行修改并 PR,也可获得相应奖励积分。文章开头的 本文永久链接 即为本文在 GitHub 上的 MarkDown 链接。

掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为掘金 上的英文分享文章。内容覆盖 AndroidiOS前端后端区块链产品设计人工智能 等领域,想要查看更多优质译文请持续关注 掘金翻译计划 、官方微博、 知乎专栏


以上所述就是小编给大家介绍的《[译] Room ???? Coroutines》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

群体智能

群体智能

James Kennedy、Russell C Eberhart、Yuhui Shi / 人民邮电出版社 / 2009-2-1 / 75.00元

群体智能是近年来发展迅速的人工智能学科领域.通过研究分散,自组织的动物群体和人类社会的智能行为, 学者们提出了许多迥异于传统思路的智能算法, 很好地解决了不少原来非常棘手的复杂工程问题.与蚁群算法齐名的粒子群优化(particle swarm optimization, 简称PSO)算法就是其中最受瞩目,应用最为广泛的成果之一. 本书由粒子群优化算法之父撰写,是该领域毋庸置疑的经典著作.作者......一起来看看 《群体智能》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具