房间 allowMainThreadQueries 与 Kotlin 协程
Posted
技术标签:
【中文标题】房间 allowMainThreadQueries 与 Kotlin 协程【英文标题】:Room allowMainThreadQueries with Kotlin coroutines 【发布时间】:2019-06-28 02:25:25 【问题描述】: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()
):
【问题讨论】:
如果数据库访问方法标记为suspend
,那么您可以使用第一种方法,否则第二种方法。
【参考方案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
【讨论】:
我需要 allowMainThreadQueries() 否则会出现运行时错误,我没有使用 MutableLiveData,只是通过 Dao 访问数据库实体 在 CoroutineScope 中,您不需要allowMainThreadQueries()
并且不会收到任何异常,这就是我的观点。这就是我正在使用的代码。没有allowMainThreadQueries()
。
不建议使用全局范围,除非您在工作后明确取消【参考方案2】:
建议在viewmodelScope
里面访问你的ViewModel中的数据库。
如果您需要从活动或片段使用访问房间数据库
lifecyclescope.launch // access database dao functions here which are suspend in definition.
或者在生命周期范围内使用 withContext(Dispatchers.IO)
更改您的线程【讨论】:
以上是关于房间 allowMainThreadQueries 与 Kotlin 协程的主要内容,如果未能解决你的问题,请参考以下文章