之前用 Android SQLDelight 查询批量数据非常方便,没想到查询单条数据反而有点搞不清。
第一种做法
这样查询就是在主线程里,即 UI 线程。实际操作很快,没有任何卡顿。
val id = args.id
if (id != 0L) {
val item = viewModel.database.itemQueries.findOne(id).executeAsOne()
binding.name.setText(item.name)
binding.number.setText(item.num.toString())
}
第二种做法
val id = args.id
if (id != 0L) {
lifecycleScope.launch(Dispatchers.IO) {
val item = viewModel.database.itemQueries.findOne(id).executeAsOne()
binding.name.setText(item.name)
binding.number.setText(item.num.toString())
}
}
但是报错:
android.util.AndroidRuntimeException: Animators may only be run on Looper threads
我不确定是不是因为在非 UI 线程里执行了更新操作,所以才报这个错误。
把 Dispatchers.IO 换成 Dispatchers.Main 就可以了。看来是这个问题。
Dispatchers.Main 与 UI 线程的关系
在 Android Kotlin 中,Dispatchers.Main
是 Kotlin 协程库中的一个调度器,它主要用于将协程分配到 Android 应用程序的主线程上执行。类似于在某个进程中开了个线程。
Android 应用程序的主线程也被称为 UI 线程,它是应用程序与用户交互的主要线程。所有用户界面操作都必须在主线程上执行,否则会出现 ANR(应用程序无响应)错误。因此,使用 Dispatchers.Main
可以确保协程中的 UI 操作在主线程上运行,避免了线程切换带来的性能消耗和潜在的错误。
例如,以下代码使用 withContext(Dispatchers.Main)
来将协程中的 UI 操作分配到主线程上:
suspend fun loadData() {
val data = withContext(Dispatchers.IO) {
// 在 IO 线程中加载数据
fetchDataFromNetwork()
}
withContext(Dispatchers.Main) {
// 在主线程中更新 UI
updateUiWithData(data)
}
}
这段代码首先将数据加载操作放在 IO 线程中执行,然后使用 withContext(Dispatchers.Main)
将 UI 更新操作切换到主线程中。这样可以保证操作不会阻塞主线程,并且可以正确地更新用户界面。
lifecycleScope 与 withContext 的区别
lifecycleScope
和 withContext
是 Kotlin 中的两个不同的概念,它们分别用于实现不同的功能。
lifecycleScope
是 Android 中的一个概念,它是 androidx.lifecycle:lifecycle-runtime-ktx
库中的一部分。它的作用是提供一个协程作用域,该协程作用域的生命周期与当前 Activity 或 Fragment 的生命周期绑定。这样可以确保在 Activity 或 Fragment 销毁时自动取消相关的协程,从而避免内存泄漏和其他问题。可以使用 lifecycleScope.launch
启动协程,并在其中执行异步任务。
withContext
是 Kotlin 标准库中的一个函数,它的作用是切换到指定的上下文执行指定的代码块。通常情况下,withContext
用于在协程中切换线程上下文,以便将某些操作从主线程转移到后台线程或者相反。例如,可以使用 withContext(Dispatchers.IO)
在 IO 线程中执行耗时的网络请求或者数据库操作,避免阻塞主线程。
因此,lifecycleScope
和 withContext
的主要区别在于它们的使用场景和作用。lifecycleScope
用于管理与界面相关的异步任务,withContext
用于协程之间的线程切换。
探索更多关于 SQLDelight
📖 Android Room 替代品 SQLDelight 中文入门教程
微信关注我哦 👍
我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式