带有Kotlin协程的房间allowMainThreadQueries

时间:2019-02-04 10:50:40

标签: android kotlin android-room kotlinx.coroutines

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

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

// 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更新)
  • 允许更简单的错误处理
  • 仅使用一个协程范围(因此不必担心范围)

1 个答案:

答案 0 :(得分:1)

您不需要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