Android SQLDelight (三) 查询数据并借助 Flow 更新到 RecyclerView

文章目录

    周五晚上直到 11 点也没有调通 Android SQLDelight Flow 的用法,由于周六早上 5 点半就要起床去参加运动会,所以就此作罢。今天去体育场路途遥远,于是路上查了一堆文档,才理清了思路。晚上回来,终于调通。

    build.gradle 配置

    dependencies {
      implementation "app.cash.sqldelight:coroutines-extensions:2.0.0-alpha05"
    }
    

    RecyclerView 监听数据变化

    lifecycleScope.launch(Dispatchers.IO) {
    	(activity as MainActivity).database.itemQueries.selectAll()
    		.asFlow()
    		.mapToList(Dispatchers.IO)
    		.collect{
    			adapter.submitList(it)
    		}
    }
    

    使用 lifecycleScope.launch 一个 coroutine,原本是为了防止阻塞 UI 线程的渲染,造成卡顿。

    但是还有一种说法:

    As kotlin flow collect is a suspend function, it needs to be executed within a coroutine.

    Kotlin 中的挂起函数(suspend functions)是一种特殊的函数类型,可以暂停当前函数的执行,等待某个操作完成后再继续执行。这种操作通常包括异步任务、网络请求、文件读写等。

    注意:

    将 SQLDelight Database 实例放到 activity 中是一种偷懒的做法,合理的方式是使用 Android Hilt 将 SQLDelight database 依赖注入 ViewModel

    为何使用 Flow

    This flow emits the query result, and emits a new result every time the database changes for that query.

    • Flow 是 LiveData 的一个更加灵活的替代方案,
    • 跨平台
    • Flow 学习门槛介于 LiveData 与 RxJava 之间

    lifecycleScope.lauch 的问题

    1. 使用 launch 是不安全的,在应用在后台时也会接收数据更新,可能会导致应用崩溃
    2. 使用 launchWhenStarted 或 launchWhenResumed会好一些,在后台时不会接收数据更新,但是,上游数据流会在应用后台运行期间保持活跃,因此可能浪费一定的资源

    https://zhuanlan.zhihu.com/p/395604351?utm_id=0

    官方推荐 repeatOnLifecycle 来构建协程。某个特定的状态满足时启动协程,并且在生命周期所有者退出该状态时停止协程。

    但是这种手动输入的场景,并不需要担心这个问题。

    ViewModel 中封装成函数

    如果不喜欢在 fragment 中写逻辑,可以封装在 ViewModel 中:

    val allItems: Flow<List<Item>> =
      itemQueries.selectAll()
        .asFlow()
        .mapToList()
    

    No value passed for parameter ‘context’ CoroutineContext

    .mapToList(Dispatchers.IO)
    

    注意

    要防止 list fragment 页被创建多次,否则这个监听 flow 流就没有意义了。

    时间都去哪儿了

    为何这么简单的操作,耗费了这么长时间?

    • SQLDelight 官方文档太潦草
    • github 上 2.0 相关的代码也很少。问 ChatGPT 也无济于事
    • Flow 及 Coroutine 相关的概念多而杂,对开发者非常的不友好。这是经历了多么变态的使用场景,才总结出如此繁杂的用法
    • Android Studio bug 多多,不知道为何新电脑上 SQLDelight 生成的代码不识别

    探索更多关于 SQLDelight

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

    参考

    • https://stackoverflow.com/questions/60359883/how-to-use-sqldelight-with-kotlin-coroutines
    • https://cashapp.github.io/sqldelight/2.0.0-alpha05/android_sqlite/coroutines/
    • 一个非常完整的示例, 一个小笔记 app https://www.section.io/engineering-education/comparing-sql-delight-to-room-database-in-android/
    • https://github.com/joseluisgs/KotlinExpert/blob/0b30ee0d5bc71980e5dc40a5ea46e2b17b607ba7/Modulo06/MyNotes/src/jvmMain/kotlin/repository/NotesRepository.kt#L4

    关于作者 🌱

    我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊,或者关注我的个人公众号“大象工具”, 查看更多联系方式