android - 在 ViewModel 与 LifeCycleOwner( Activity/fragment )中启动协程

标签 android kotlin kotlin-coroutines android-viewmodel coroutinescope

在 ViewModel 中启动协程或使用 suspend 标记 ViewModel 函数更好吗?修饰符并在 Activity/fragment 本身中启动协程?
在 ViewModel 中启动:

class MainViewModel: ViewModel() {
  fun addNewItem(item: Item) {
    viewModelScope.launch {
      // Add the item to database
    }
  }
}
class ItemsFragment: Fragment() {
  fun onButtonClick() {
    viewModel.addNewItem(Item())
  }
}
在 LifeCycleOwner 中启动:
class MainViewModel: ViewModel() {
  suspend fun addNewItem(item: Item) {
    // Add the item to database
  }
}
class ItemsFragment: Fragment() {
  fun onButtonClick() {
    lifecycleScope.launchWhenStarted {
      viewModel.addNewItem(Item())
    }
  }
}

最佳答案

这真的取决于你的用例,如果你想将任务绑定(bind)到 viewModelScope或 View 的 lifecycleScope .
为了更好地理解,请考虑以下两个示例:

  • 用户触发刷新 - 可能你不想将它与 View 的 lifecycleScope 联系起来,因为如果发生方向更改,您的任务将被终止,您将不得不再次重新开始获取数据。
  • 动画或其他查看相关任务 - 假设您必须对与 View 布局方式相关的动画进行一些计算。在这种情况下,在方向更改后,您可能需要重新计算,因为 View 发生了变化。

  • 一般来说,你更有可能遇到我相信的第一种情况。
    在您的情况下,添加项目进入第一个用例,因为假设您直接从 View 启动并使用 lifecycleScope来自 Fragment/Actvity ,在这种情况下,如果 suspend保存仍在运行并且发生方向更改,任务将被终止,您的用户会想知道为什么没有添加该项目。
    话虽如此,数据库操作通常运行得如此之快,以至于上述场景将难以重现,但出于测试目的抛出 api 请求或延迟,您可以查看理论。

    关于android - 在 ViewModel 与 LifeCycleOwner( Activity/fragment )中启动协程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67946859/

    相关文章:

    android - 使用 SmsRetriever 时接收广播 Intent 时出错

    Kotlin For 循环从给定的索引开始

    android - 从另一个 Activity 中调用dialog.dismiss

    android - androidx.paging.DataSource.Factory 时 Room 无法检索数据(使用 LiveData + Kotlin 协程)

    kotlin - 为什么 kotlin 协程中的 launch 会吞下异常?

    java - 启动画面有时只显示

    android - NFC Controller 和 POS 读卡器之间的初始握手

    android - 协程限制?

    java - 检查 fragment 当前是否可见

    android - 从配套移动应用程序的环境模式唤醒穿戴设备