android - Room allowMainThreadQueries 与 Kotlin 协程

标签 android kotlin android-room kotlinx.coroutines

官方 Android 文档指出不推荐使用 allowMainThreadQueries(),因为它可能会长时间锁定 UI 并触发 ANR。 但是 Kotlin 协程让我们有可能在主线程中执行一些操作而不会有效地阻塞 UI。

所以我想问:使用 allowMainThreadQueries() 并在主线程上运行的协程范围内访问数据库是否安全?如下所示:

// WITH allowMainThreadQueries()
val activityJob = Job()
val mainScope = CoroutineScope(Dispatchers.Main + activityJob)
mainscope.launch {

    // access room database and retrieve some data

    // update UI with data retrived

}

或者我们应该坚持不允许主线程查询并在另一个线程中执行数据库查询的旧方法?

// WITHOUT allowMainThreadQueries()
val activityJob = Job()
val defaultScope = CoroutineScope(Dispatchers.Default + activityJob)
val mainScope = CoroutineScope(Dispatchers.Main + activityJob)
defaultScope.launch {

    // access room database and retrieve some data

    mainScope.launch {
        // update UI with data retrived
    }

}

我问是因为前一种方式(使用 allowMainThreadQueries()):

  • 更具可读性(我可以在访问数据库的函数的相同协程上下文中更新 UI,而无需担心在另一个协程范围内启动 UI 更新)
  • 允许更简单的错误处理
  • 只使用一个协程范围(因此需要关心的范围更少)

最佳答案

你不应该需要 allowMainThreadQueries() 来让它工作。作用域协程在其线程中执行。

这是我不久前做的:

@UiThread
fun getUsers(context: Context): LiveData<List<User>> {
    if (!::users.isInitialized) {
        users = MutableLiveData()
        users.postValue(MyDatabase.get(context).users().getAll())
        GlobalScope.launch(Dispatchers.Main) {
            val usersFromDb: List<User> = async(Dispatchers.IO) {
                return@async MyDatabase.get(context).users().getAll()
            }.await()
            users.value = usersFromDb
        }
    }
    return users
}

您可以看到这个 getUsers() 方法从主线程调用,返回一个 LiveData(在这种情况下很方便)。数据库查询发生在 GlobalScope.launch() 中。

是的,您的设计是我个人喜欢的。一个有效的。但我认为您根本不需要 allowMainThreadQueries()。请随意阅读(我的)博客文章:https://proandroiddev.com/android-viewmodel-livedata-coroutines-contraption-e1e44af690a6

关于android - Room allowMainThreadQueries 与 Kotlin 协程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54514572/

相关文章:

android - 如何在android shell中制作一行for循环

android - codegen生成的适配器构造函数中的 `moshi`是什么意思?

regex - Kotlin 正则表达式边界匹配不工作

android - 使用 concat 从 DB 请求数据,如果它从 Service 中空获取不工作?

android - 房间数据库 Livedata getValue() 返回 null

android - 如何将现有的 SQLite 应用程序迁移到 Room Persistence Library?

android - float 按钮不显示阴影

android - 关于 OpenGL ES 2 的问题

android - 如何移动/拖动包含一堆形状的整个 android View ?

android-studio - 除了枚举注释外,kotlin Android还可以替代枚举吗?