MainScope和lifecycleScope最重要的区别在于启动协程的取消管理。
我知道你的问题是关于 requireActivity().lifecycleScope,但让我一步一步来。
使用生命周期范围,取消会自动为您完成 - 在 Fragment 或 Activity 的 onDestroy() 事件中,具体取决于您挂钩的生命周期。
使用 mainScope,您只能靠自己,并且必须自己添加 scope.cancel(),如下所示:
class MyActivity: Activity {
private val scope = MainScope()
// launch a coroutine on this scope in onViewCreated
override fun onDestroy() {
super.onDestroy()
//you have to add this manually
scope.cancel()
}
}
更多信息请访问:
https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-main-scope.html
换句话说,你在主范围内手动做的事情(或应该做的事情),lifecycleScope 为你做的事情自动。
现在,此时,您可以(也许)说,啊哈 - 这是我想要的主要 Scope,因为我的操作不会自动取消,这正是我想要的,所以我可以跳过添加取消调用.
在某种程度上,是的,你会得到你想要的,因为它确实会继续运行一段时间,直到 Fragment 及其变量被垃圾收集,但你将不再可以访问该范围 - 片段消失了,当您再次导航到片段时,将创建一个新实例以及一个新的主范围。当然,您无法保证在垃圾收集开始之前需要多长时间。那么异常呢?
现在转到 requireActivity().lifecycleScope。
如果你使用 requireActivity().lifeCycleScope,你显然会跳上 Activity 生命周期并获得两个好处 - 更长的生命周期(大概是 Activity 中还有其他片段,并且说从有问题的片段导航回来只是导航到同一活动中的另一个片段,并且不退出应用程序),并在 OnDestroy() 中自动取消。
这可能就足够了。但是a)如果您需要,您的作业句柄仍将保留在片段中,并且再次,一旦您丢失片段,您将无法再访问该作业(假设您需要它),并且b)您的活动将无法在配置更改中幸存(除非您明确禁止它们)。如果您想允许和处理配置更改,请在 Activity 上使用 viewModelScope(并在 Activity 和 Fragment 之间使用共享视图模型)。
The ViewModel class allows data to survive configuration changes such as screen rotations.
最后,如果这些都不够(您的“Db 保存”操作需要很长时间),请使用服务(或 WorkManager 等)。但到那时,要问的正确问题将是“为什么要花这么长时间?”并专注于此。