问题描述
是在 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())
}
}
}
解决方法
这实际上取决于您的用例以及您是否希望将任务与 viewModelScope
或视图的 lifecycleScope
相关联。
为了更好地理解,请考虑以下两个示例:
-
用户触发刷新 - 可能您不想将其与视图的
lifecycleScope
相关联,因为在发生方向更改的情况下,您的任务将被终止,而您'必须重新开始获取数据。 - 动画或其他与视图相关的任务 - 假设您必须对与视图布局方式相关的动画进行一些计算。在这种情况下,在方向更改后,您可能需要重新计算内容,因为视图已更改。
一般来说,您更有可能遇到我认为的第一种情况。
在您的情况下,添加项目进入第一个用例,因为假设您直接从视图启动并使用 lifecycleScope
中的 Fragment/Actvity
,在这种情况下,如果 {{1}保存仍在运行并且发生方向更改,任务将被终止,您的用户会想知道为什么没有添加该项目。
话虽如此,db 操作通常运行得如此之快,以至于上述场景很难重现,但为了测试目的而抛出 api 请求或延迟,您可以查看理论。