为什么不建议使用 GlobalScope?
- 当我们使用GlobalScope启动协程时,它将在顶级协程中启动,因为它是全局的,并且会一直保留到您的应用程序死掉为止。
换句话说:
- 如果你 GlobalScope用来启动一个协程,即使你跳过了特定的活动,它也会一直存活到你的应用程序死掉 || 启动特定 Corotuine 的片段。
- 正如您已经知道的那样,协程是轻量级的,但Will Consume Some Memory Resources在它肯定运行时仍然如此,这可能会导致您的应用程序中的内存泄漏。
解决方案
- 您可以使用预定义的范围,例如lifecycleScope{…},如果您正在使用 ViewModel(s),您可以使用viewModelScope{…}它来启动协程并开始使用。
实际差异
让我们测试两者GlobalScope{…}并lifecycleScope{…}更好地理解
- 我创建了两个片段并通过导航组件在两个片段之间添加了导航。
第一个片段的 XML:
第二个片段的 XML:
讲真话的时间🔥
在进一步Make Sure说明您已包含协程依赖项(如果未包含)之前:
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0'
在 First Fragment 的 Kotlin 文件中:
在GlobalScope{…}
- GlobalScope{…}当按下按钮时,主要协程将被启动。
- 当按下按钮时,每次都会以第二个延迟运行无限循环。
- 延迟 5 秒后,将启动第二个片段,如下代码所示:
view.toSecondFragment.setOnClickListener {
GlobalScope.launch{
while (true) {
delay(1000L)
Log.d("From GlobalScope", "Global Scope Is Still Running")
}
}
GlobalScope.launch(Dispatchers.Main){
delay(5000L)
Navigation.findNavController(view).navigate(R.id.firstFragment_to_secondFragment)
}
}
- 现在在成功构建后启动应用程序:
- 正如你所看到的,即使第一个片段已经死了,我们的循环仍然继续,因为我们声明了我们的范围,GlobalScope{…}它将继续运行,直到我们的应用程序死了。
- 这是在 Kotlin-Coroutines 中不鼓励使用 GlobalScope 的主要原因。
在lifecycleScope{…}
- lifecycleScope{…}当按下按钮时,主要协程将被启动。
- 当按下按钮时,每次都会以第二个延迟运行无限循环。
- 延迟 5 秒后,将启动第二个 Fragment。
正如您viewLifecycleOwner在启动协程之前提到的代码中所见lifecycleScope{…}
- 这是因为我正在处理片段。viewLifecycleOwner当 Fragment 有它的 UI 时添加 ( onCreateView() , onDestroyView() )这是添加到 Fragment 的整体生命周期( onCreate() , onDestroy() )。
- 以防万一,如果您正在从事活动,则无需提及viewLifecycleOwner。
view.toSecondFragment.setOnClickListener {
viewLifecycleOwner.lifecycleScope.launch{
while (true) {
delay(1000L)
Log.d("From LifeCycleScope", "LifeCycleScope Is Still Running")
}
}
viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Main){
delay(5000L)
Navigation.findNavController(view).navigate(R.id.firstFragment_to_secondFragment)
}
}
- 现在在成功构建后启动应用程序:
- 如您所见,一旦片段死亡,协程执行就停止了。
同样意味着viewModelScope{…}同样,它也将执行与 相同lifecycleScope{…}。但是viewModelScope{…}当你使用 ViewModel(s) 时你会用到。
结论
- 当您希望操作GlobalScope{…}运行直到应用程序死机时使用,如果不是,您绝对应该使用lifecycleScope{…}.
- 如果您正在使用 ViewModel(s),您可以使用viewModelScope{…}.
最后,如果大伙有什么好的学习方法或建议欢迎大家在评论中积极留言哈,希望大家能够共同学习、共同努力、共同进步。