房间allowMainThreadQueries与科特林协程

问题描述 投票:3回答:1

Android官方文档指出使用allowMainThreadQueries()不建议,因为它可以锁定为长期用户界面,并引发ANR。但科特林协程给了我们在主线程中没有有效地阻止了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()):

  • 是更可读(I可以更新在访问该数据库中的相同功能的协程上下文的用户界面中,不承载有关在另一个协程范围启动UI更新)
  • 允许简单的错误处理
  • 利用只有一个协程范围(所以欠范围关心)
android kotlin android-room kotlinx.coroutines
1个回答
1
投票

你不应该需要allowMainThreadQueries()这个工作。作用域协程executs在其线程。

这是我做的不是早就说过:

@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

© www.soinside.com 2019 - 2024. All rights reserved.