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

Ant*_*oro 5 android android-fragments android-activity kotlin-coroutines

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

代码示例:

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

MainScope().launch { 
        // suspend function invocation
}
Run Code Online (Sandbox Code Playgroud)

Dmi*_*tri 2

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

\n

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

\n

使用生命周期作用域,取消会自动为您完成 - 在 Fragment 或 Activity 的 onDestroy() 事件中,具体取决于您挂钩的生命周期。

\n

使用 mainScope,您\xe2\x80\x99 就只能由您自己完成,并且必须自己添加scope.cancel(),如下所示:

\n
class MyActivity: Activity {\n    private val scope = MainScope()\n    // launch a coroutine on this scope in onViewCreated\n    override fun onDestroy() {\n        super.onDestroy()\n        //you have to add this manually\n        scope.cancel()\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n
\n

更多信息位于:\n https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-main-scope.html

\n
\n

换句话说,您在主作用域中手动执行(或应该执行)的操作,lifecycleScope 会自动为您完成。

\n

现在,此时,你可以(也许)说,啊哈 - 这是我想要的主要作用域,因为我的操作不会自动取消,它\xe2\x80\x99正是我想要的,所以我可以跳过添加取消电话。

\n

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

\n

现在转到requireActivity().lifecycleScope。

\n

如果您使用 requireActivity().lifeCycleScope,您显然会跳转到 Activity 生命周期并获得两个优势 - 更长的生命周期(大概,活动中还有其他片段,并且说从有问题的片段导航回来只是导航到另一个片段在同一个活动中,并且不退出应用程序),并在 OnDestroy() 中自动取消。

\n

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

\n

ViewModel 类允许数据在配置更改(例如屏幕旋转)中保留下来。

\n

最后,如果这些都不够(您的 \xe2\x80\x9cDb save\xe2\x80\x9d 操作需要很长时间),请使用服务(或 WorkManager 等)。但到那时,要问的正确问题将是 \xe2\x80\x9c 为什么要花这么长时间?\xe2\x80\x9d 并专注于此。

\n