使用“MainScope()”和“requireActivity().lifecycleScope”在片段内启动协程有什么区别?

What's the difference between launching a coroutine inside a fragment using `MainScope()` and `requireActivity().lifecycleScope`?

启动需要在片段生命周期后继续的操作(例如数据库写入)是否有意义?

代码示例:

requireActivity().lifecycleScope.launch {
         // suspend function invocation
}

MainScope().launch { 
        // suspend function invocation
}

MainScopelifecycleScope最重要的区别在于启动协程的取消管理。

我知道你的问题是关于 requireActivity().lifecycleScope 的,但让我一步一步来。

使用 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()
    }
}

More info at: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-main-scope.html

换句话说,您使用主作用域手动做什么(或应该做什么),lifecycleScope 会自动 为您做。

现在,在这一点上,你可以(也许)说,啊哈 - 这是我想要的主要范围,因为我的操作不会自动取消,这正是我想要的,所以我可以跳过添加取消通话。

在某种程度上,是的,你会得到你想要的,因为它确实会保持 运行 一段时间 不确定 直到片段及其变量被垃圾收集,但您将无法再访问该范围 - 片段消失了,当您再次导航到该片段时,将创建一个新实例以及一个新的主范围。当然,您无法保证在垃圾收集开始之前需要多长时间。那么异常呢?

现在进入 requireActivity().lifecycleScope.

如果你使用requireActivity().lifeCycleScope,你显然跳上了Activity生命周期并获得了两个好处——更长的生命周期(估计还有其他片段在activity,并说从有问题的片段返回导航只是导航到同一 activity 中的另一个片段,而不是退出应用程序),并在 OnDestroy() 中自动取消。

这可能就足够了。但是 a) 你的工作句柄,如果你需要的话,仍然会留在片段中,再一次,一旦你丢失了片段,你就无法再访问该工作(假设你需要它),和 b)你的 activity 不会在配置更改后继续存在(除非您明确禁止它们)。如果您想允许和处理配置更改,请使用 activity 上的 viewModelScope(并在 activity 和片段之间使用共享视图模型)。

The ViewModel class allows data to survive configuration changes such as screen rotations.

最后,如果 none 就足够了(您的“数据库保存”操作需要很长时间),请使用服务(或 WorkManager 等)。但到那时,应该问的正确问题是“为什么要花这么长时间?”并专注于此。