简体   繁体   English

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

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

Does that make sense to launch operations, like db writes, that needs to continue after the fragment lifecycle?这对启动需要在片段生命周期之后继续的操作(如数据库写入)有意义吗?

Code sample:代码示例:

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

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

The most important difference between MainScope and lifecycleScope is in the cancellation management of the launched coroutine. MainScopelifecycleScope最重要的区别在于启动协程的取消管理。

I know your question is about requireActivity().lifecycleScope, but let me do it step by step.我知道你的问题是关于 requireActivity().lifecycleScope,但让我一步一步来。

With lifecycleScope, cancellation is done for you automatically - in the onDestroy() event in either Fragment or Activity, depending on whose lifecycle your hooked into.使用生命周期范围,取消是自动为您完成的 - 在 Fragment 或 Activity 的 onDestroy() 事件中,这取决于您挂钩的生命周期。

With the mainScope, you're on your own, and would have to add the scope.cancel() yourself, like below:使用 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更多信息请参见:https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-main-scope.ZFC35FZ30D52C7A5E396

In other words, what you do (or supposed to do) manually with main scope, lifecycleScope does it for you automatically .换句话说,您使用主 scope手动执行(或应该执行)的操作,生命周期范围会自动为您执行。

Now, at this point, you could (maybe) say, aha - it is the main Scope that I want, because my operation is not automatically cancelled, it's exactly what I want, so i can just skip adding the cancellation call.现在,在这一点上,你可以(也许)说,啊哈 - 这是我想要的主要 Scope,因为我的操作不会自动取消,这正是我想要的,所以我可以跳过添加取消调用。

In a way, yes, you will get what you wish, as indeed it will keep running for some indeterminate perid of time until the Fragment and its variables are garbage collected, but you will no longer have access to that scope - the fragment is gone, and when you navigate into the fragment again, a new instance is going to be created, along with a new main scope.在某种程度上,是的,你会得到你想要的,因为它确实会继续运行一段不确定的时间,直到 Fragment 及其变量被垃圾收集,但你将无法再访问那个 scope - 片段消失了,当您再次导航到片段时,将创建一个新实例,以及一个新的主 scope。 And of course you have no guarantee on how long it is going to be before the garbage collection kicks in. And what about exceptions?当然,您无法保证在垃圾收集开始之前需要多长时间。那么异常呢?

Now on to requireActivity().lifecycleScope.现在到requireActivity().lifecycleScope。

If you use requireActivity().lifeCycleScope, you obviously jump on the Activity lifecycle and get two advantages - a longer life cycle (presumably, there are other fragments in the activity, and say navigation back from the fragment in question just navigates to another fragment within the same activity, and not exits the app), and automatic cancellation in OnDestroy().如果你使用 requireActivity().lifeCycleScope,你显然会跳上 Activity 生命周期并获得两个优势 - 更长的生命周期(大概是 Activity 中还有其他片段,并且说从有问题的片段返回只是导航到另一个片段在同一个活动中,并且不退出应用程序),并在 OnDestroy() 中自动取消。

That may be enough.这可能就足够了。 But a) your job handle, if you need one, will still stay in the fragment, and yet again, once you lose the fragment, you no longer have access to the job (assuming you need it), and b) your activity will not survive a configuration change (unless you expressly prohibit them).但是a)如果您需要,您的工作句柄仍将保留在片段中,并且再次,一旦您丢失片段,您将无法再访问该工作(假设您需要它),并且b)您的活动将无法在配置更改中幸存(除非您明确禁止它们)。 If you want to allow and handle configuration changes, go with the viewModelScope on the activity (and use a shared view model between activity and fragment).如果要允许和处理配置更改,go 与活动上的 viewModelScope(并在活动和片段之间使用共享视图 model)。

The ViewModel class allows data to survive configuration changes such as screen rotations. ViewModel class 允许数据在屏幕旋转等配置更改中保留下来。

And, finally, if none of that is enough (your “Db save” operation is taking a really long time), use a Service (or WorkManager, etc).最后,如果这些都不够(您的“Db 保存”操作需要很长时间),请使用服务(或 WorkManager 等)。 But at that point, the proper question to ask will be “why is it taking so long?”但到那时,要问的正确问题将是“为什么要花这么长时间?” and focus on that.并专注于此。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 viewLifecycleOwner 的 lifecycleScope 从 Fragment 启动协程 - Launching a coroutine from a Fragment using viewLifecycleOwner's lifecycleScope requireActivity 和 onActivityCreated 有什么区别 - What is the difference between requireActivity and onActivityCreated 无法在 lifecycleScope 协程中添加片段 - Cant add fragment inside of lifecycleScope coroutine 为什么片段的上下文在lifecycleScope中为空 - Why the fragment's context null inside lifecycleScope LifecycleScope.launch 与 onViewCreated 内的协程 - lifecycleScope.launch vs coroutine inside onViewCreated 如果我可以将 Flow 和 StateFlow 与生命周期范围 \ viewLifecycleOwner.lifecycleScope 一起使用,那么在 ViewModel 中使用 LiveData 有什么意义 - What's the point of using LiveData in ViewModel if I can use Flow and StateFlow with lifecycleScope \ viewLifecycleOwner.lifecycleScope 分离片段和删除片段有什么区别? - What's the difference between detaching a Fragment and removing it? Retrofit2 是否带协程,有什么区别? - retrofit2 with coroutine or not, what's the difference? 使用savedInstance 保存和片段的参数有什么区别? - What is the difference between saving with savedInstance and the fragment's argument? 在片段中使用 requireActivity() 或 getActivity() - use requireActivity() or getActivity() in fragment
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM