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()
):
你不应该需要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