【问题标题】:What is the correct way to use Android Room with Kotlin Coroutines?将 Android Room 与 Kotlin Coroutines 一起使用的正确方法是什么?
【发布时间】:2020-09-13 05:34:21
【问题描述】:

最近在学习如何使用 Kotlin Coroutines 时,阅读了几篇相关文章。但是其中一个让我感到困惑:Coroutines On Android (part III): Real work

正如它所指出的:

注意:Room 使用自己的调度程序在后台运行查询 线。您的代码不应使用 withContext(Dispatchers.IO) 来调用 暂停房间查询。它会使代码复杂化并使您的 查询运行速度较慢。

当时我看到这一段似乎很有道理,但是当我打开一个 Android 项目并尝试深入研究时,问题出现了,Android Studio 警告我:

暂停函数“yourMethod”只能从协程中调用 或其他挂起功能

我现在在这里冻结,因为文章告诉我不要使用withContext(Dispatchers.IO)。我现在想知道我应该使用withContext(Dispatchers.Main) 还是使用GlobalScope.launch 来运行我的查询?

【问题讨论】:

  • “我现在想知道我应该使用 withContext(Dispatchers.Main) 还是使用 GlobalScope.launch 来运行我的查询?” -- 使用launch()(或者async()await())和一个合适的CoroutineScope。那可能是GlobalScope,但通常有更好的选择(viewModelScopeViewModel 上,lifecycleScope 在活动上,viewLifecycleScope 在片段上,自定义CoroutineScope 如看到的here 等。
  • @CommonsWare 谢谢,我正在寻找一个不应该被取消的工作的解决方案,你提供的链接正是我正在寻找的,我会检查一下。感谢您的帮助!
  • 如果您不想取消暂停有趣的操作,请尝试 withContext(NonCancellable) {}
  • @sasikumar 您的解决方案似乎对这个问题没有帮助。项目中的“suspend”关键字被 Android Studio 标记为“冗余”。

标签: android kotlin android-room kotlin-coroutines


【解决方案1】:

我也是协程的新手,这是我目前所了解的。如果我想与数据库交互,我会这样做

lifecycleScope.launch {
        //this is still the main thread
        //interact with database
        NoteDatabase(this).getNoteDao().addNote(Note(id=0, title = "TITLE", note = "BODY"))
        //signature of addNote: @Insert suspend fun addNote(note: Note)
}

使用生命周期范围可确保您在销毁活动或片段后不执行任何操作,但使用 GlobalScope 可能更有意义,因为您不希望在退出您编辑的活动时取消添加/保存操作一个数据库条目。

当使用“挂起”时,不能保证函数是非阻塞的。如果存在阻塞代码,则更改协程上下文是程序员的责任。我确认 Room 确实通过检查构建来改变上下文,所以你不必担心自己改变上下文:

【讨论】:

    猜你喜欢
    • 2018-05-07
    • 2017-08-25
    • 1970-01-01
    • 2018-04-10
    • 2013-01-02
    • 1970-01-01
    • 2020-08-27
    • 2020-07-10
    • 2020-09-29
    相关资源
    最近更新 更多