到目前为止,每当我想访问数据库时,我都会使用这种模式:

runBlocking {
    launch {
        // fetch something from the database and put it to some view
    }
}

现在,我正在深入研究Kotlin 合作项目,我越来越确信,这是一种糟糕的模式.基本上,我可能只有allowMainThreadQueries个,因为我的模式无论如何都会阻塞主线程.

不幸的是,我还没有找到一个合适的模式.如何有效地使用Kotlins协程来访问数据库?

runBlocking是合作项目的唯一入口吗?

考虑以下情况:

override fun onCreate() {
    setContentView(someLayout)

    // concurrently fetch something from the database and put it in some view
    // onCreate may return before this has finished

    someButton.setOnClickListener {
        // concurrently insert or update something in the database
    }
}

推荐答案

你应该在Android项目中使用runBlocking,除非你将Kotlin协程代码与一些不能使用协程的Java代码混合在一起,并且它需要一种方法在自己的后台线程上以阻塞方式调用某些协程.在这种情况下,您可以使用runBlocking为Java代码创建一个桥函数来调用,但是您永远不会从Kotlin调用这个函数,当然也永远不会从主线程调用它.在主线程上调用阻塞代码会冻结UI,这会让你的应用程序感觉不舒服,并有触发ANR(应用程序无响应)错误的风险.

开始协同程序的正确方法是使用协同程序示波器启动协同程序.Android Jetpack框架已经为您提供了活动、片段和视图模型.

在活动中,使用lifecycleScope.launch.在片段中,通常应该使用viewLifecycleOwner.lifecycleScope.launch.在ViewModel中,使用viewModelScope.launch.

用一个协同视野而不是runBlocking能做什么?它可以防止长时间运行的挂起操作(如从磁盘读取数据库)阻塞主线程并冻结用户界面.当Activity/Fragment/ViewModel被删除时,它会自动取消长期运行的工作,因此它可以防止内存泄漏和资源浪费.

Android相关问答推荐

如何让用户与我的应用生成的多个音频文件交互

Android开发:主题排版不适用于按钮文本

如何更新Kotlin中的显示?

如何使可拖动内容停留在可组合框的边界内

如何在Android Studio的LinearLayout中禁用阴影

在内部创建匿名对象的繁忙循环调用函数会产生开销吗?

从包含的(复合)模块导入 Kotlin 类时,Android 应用程序模块的 build.gradle.kts 未解决的引用错误

是什么导致调用 Firebase 服务器?

如何在 Android 的 ViewModel 中使用 LiveData

在单元测试下断言协程未完成

ArrayList 上的 Android intent.getParcelableArrayListExtra 引发 Nullpointer 异常

Jetpack compose (Glance) 小部件在加载位图图像后不会重新组合

在 Jetpack Compose 的无状态 Compose 中管理条件逻辑

如何像 XML 一样在 Compose Android Studio 中折叠/展开小部件代码区域/区域

PayUCheckoutPro Android SDK 实现问题

在 Jetpack Compose 中清除列表时可组合不重组

插入查询室 OnConflictStrategy.REPLACE

无法使用 Gradle 托管设备对基线配置文件运行测试

禁用通知权限后启动前台服务导致崩溃(Android 13)

设备文件资源管理器-ROOM 数据库中的数据库文件夹为空