Android SQLDelight (五) 查询单条数据库记录,并更新 UI

更新日期: 2023-05-26 阅读次数: 744 字数: 807 分类: Android

之前用 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 的区别

lifecycleScopewithContext 是 Kotlin 中的两个不同的概念,它们分别用于实现不同的功能。

lifecycleScope 是 Android 中的一个概念,它是 androidx.lifecycle:lifecycle-runtime-ktx 库中的一部分。它的作用是提供一个协程作用域,该协程作用域的生命周期与当前 Activity 或 Fragment 的生命周期绑定。这样可以确保在 Activity 或 Fragment 销毁时自动取消相关的协程,从而避免内存泄漏和其他问题。可以使用 lifecycleScope.launch 启动协程,并在其中执行异步任务。

withContext 是 Kotlin 标准库中的一个函数,它的作用是切换到指定的上下文执行指定的代码块。通常情况下,withContext 用于在协程中切换线程上下文,以便将某些操作从主线程转移到后台线程或者相反。例如,可以使用 withContext(Dispatchers.IO) 在 IO 线程中执行耗时的网络请求或者数据库操作,避免阻塞主线程。

因此,lifecycleScopewithContext 的主要区别在于它们的使用场景和作用。lifecycleScope 用于管理与界面相关的异步任务,withContext 用于协程之间的线程切换。

探索更多关于 SQLDelight

📖 Android Room 替代品 SQLDelight 中文入门教程

tags: sqldelight

关于作者 🌱

我是来自山东烟台的一名开发者,有敢兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式