CoroutineScope(Dispatchers.IO).launch与GlobalScope.launch的差异及运行疑问
问题解答
为什么你创建的CoroutineScope协程未停止?
你直接通过CoroutineScope(Dispatchers.IO)创建的是一个无生命周期绑定的独立作用域,它没有关联Activity的生命周期回调,因此不会在Activity跳转或销毁时自动取消协程。只有当你手动调用该Scope的cancel()方法,或者协程自身执行完成、进程终止时,协程才会停止。
CoroutineScope(自定义)与GlobalScope的核心差异
1. 生命周期关联能力
- GlobalScope:全局单例作用域,生命周期与应用进程完全绑定。除非手动取消单个协程,或者应用进程被杀死,否则它启动的协程会一直运行。它没有父Job,无法批量取消所有子协程。
- 自定义CoroutineScope:默认创建的无关联Scope和GlobalScope表现类似,但它支持通过绑定父Job或生命周期Owner(如Activity、ViewModel)实现自动取消。比如AndroidX提供的
lifecycleScope(Activity/Fragment级)、viewModelScope(ViewModel级),都是封装好的自定义Scope,会在对应生命周期结束时自动取消所有子协程。
2. 取消机制
- GlobalScope:只能针对单个协程调用
cancel(),无法通过父作用域批量取消所有由它启动的协程,容易出现协程泄漏。 - 自定义CoroutineScope:若创建时传入父Job(如
CoroutineScope(Dispatchers.IO + Job())),调用Scope的cancel()即可一次性取消所有子协程;绑定生命周期后,无需手动调用cancel,系统会自动处理。
3. 结构化并发合规性
- GlobalScope:违背结构化并发原则,因为它的协程脱离了业务逻辑的生命周期边界,长期运行的协程可能导致内存泄漏、后台资源浪费。官方明确不推荐在业务代码中使用。
- 自定义CoroutineScope:可以根据业务场景创建对应粒度的作用域(页面级、组件级),明确协程的生命周期边界,符合结构化并发的设计思想,便于维护和管理。
正确的Activity内协程用法示例
推荐使用AndroidX提供的lifecycleScope,自动关联Activity生命周期:
lifecycleScope.launch(Dispatchers.IO) { for (i in 0 until 10000) { delay(500) LogUtils.debug("Coroutine", "Lifecycle_Scope") } }
或者手动创建绑定生命周期的Scope,并在onDestroy时取消:
private val activityScope = CoroutineScope(Dispatchers.IO + lifecycle.coroutineContext.job) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) activityScope.launch { for (i in 0 until 10000) { delay(500) LogUtils.debug("Coroutine", "Custom_Scope") } } } override fun onDestroy() { super.onDestroy() activityScope.cancel() }
内容的提问来源于stack exchange,提问作者siva1992
相关产品推荐
相关产品推荐

