【问题标题】:Launching a coroutine in ViewModel vs LifeCycleOwner (Activities/fragments)在 ViewModel 与 LifeCycleOwner(活动/片段)中启动协程
【发布时间】:2021-08-28 23:29:49
【问题描述】:

是在 ViewModel 中启动协程更好,还是在 ViewModel 函数中使用suspend 修饰符标记并在 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())
    }
  }
}

【问题讨论】:

    标签: android kotlin kotlin-coroutines android-viewmodel coroutinescope


    【解决方案1】:

    这实际上取决于您的用例,以及您是否想将任务绑定到 viewModelScope 或视图的 lifecycleScope

    为了更好地理解,请考虑以下两个示例:

    1. 用户触发刷新 - 可能您不想将其绑定到视图的 lifecycleScope,因为如果方向更改,您的任务将被终止,您必须重新启动再次获取数据。
    2. 动画或其他与视图相关的任务 - 假设您必须对与视图布局方式相关的动画进行一些计算。在这种情况下,在方向改变后,您可能需要重新计算,因为视图发生了变化。

    一般来说,您更有可能遇到我认为的第一种情况。

    在您的情况下,添加项目进入第一个用例,因为假设您直接从视图启动并使用来自Fragment/ActvitylifecycleScope,在这种情况下,如果suspend 保存仍在运行并且发生方向更改,任务将被终止,您的用户会想知道为什么没有添加该项目。

    话虽如此,db 操作通常运行得如此之快,以至于上述场景将难以重现,但出于测试目的抛出 api 请求或延迟,您可以查看理论。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多