持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第11天,点击查看活动详情
前言
上一篇我们了解了协程的构造器和调度器,这一篇我们来了解一下常见的协程作用域。
协程作用域
在 Kotlin 中,协程必须在称为CoroutineScope的东西中运行。CoroutineScope 会跟踪协程,甚至是暂停的协程。为了确保跟踪所有协程,Kotlin 不允许在没有 CoroutineScope 的情况下启动新的协程。
全局作用域(GlobalScope)
- 当协程在全局范围内启动时,它们的生命周期与应用程序一样长,除非是主进程退出否则只要该协程不结束就会一直占用资源,这样会出现很大的风险,比如说协程体中的代码出现异常,我们是无法释放的,这样就会造成设备资源异常消耗,从而内存泄漏应用崩溃。
- 在全局范围内启动的协程将在单独的线程中启动,当存在多个协程时便会排队同步的执行,而不像多线程一样异步的争抢CPU资源。
GlobalScope.launch(Dispatchers.Main) {
val fA = async(Dispatchers.IO) { functionA() }
val fB = async(Dispatchers.IO) { functionB() }
// 返回UI线程
functionC(fA.await(), fB.await())
}
生命周期作用域(LifeCycleScope)
具有生命周期的协程,是LifecycleOwner的扩展属性,是由Lifecycle Ktx库提供的能力,用于与具有生命周期感知的组件一起使用,生命周期销毁同时销毁该协程作用域,从而不会造成内存泄漏。
- 引入
androidx.lifecycle:lifecycle-runtime-ktx:2.4.0
Activity中使用 由于Activity中实现了LifecycleOwner接口,所以可以在Activity中使用LifeCycleScope
class LifeCycleScopeActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_layout)
//通过lifecycleScope创建协程
lifecycleScope.launch {
// 执行相关的耗时业务逻辑
...
}
}
}
在LifeCycleScope中默认的线程是主线程,我们可以通过其他方式来切换线程。
// 第一种
lifecycleScope.launch {
withContext(Dispatchers.IO){
// 执行相关的耗时业务逻辑
Logger.d("第一种${Thread.currentThread().name}")
}
}
// 第二种
lifecycleScope.launch(Dispatchers.IO) {
// 执行相关的耗时业务逻辑
Logger.d("第二种${Thread.currentThread().name}")
}
ViewModel作用域( ViewModelScope)
为应用中的每个 ViewModel 定义了 ViewModelScope。如果 ViewModel 销毁会调用clear方法,然后调用CoroutineContext的cancel方法,则在此范围内启动的协程都会自动取消。如果具有仅在 ViewModel 处于活动状态时才需要完成的工作,此时协程非常有用。
- 引入
androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0
ViewModel中使用 由于ViewModel
class CoroutineViewModel : ViewModel() {
fun functionA(){
viewModelScope.launch(Dispatchers.IO) {
// 执行业务逻辑
}
}
}