本篇文章主要是讲解如何使用lifecycle创建协程 、源码解析以及lifecycle在协程中的应用。
lifecycle
创建协程private fun test55() {
//创建协程
lifecycleScope.launch {
}
}
如上很简单,如果想要和Activity的生命周期
绑定,还有下面一系列方法供你使用:
private fun test55() {
//创建协程
lifecycleScope.launchWhenResumed { }
lifecycleScope.launchWhenCreated { }
lifecycleScope.launchWhenStarted { }
}
只有当对应生命周期执行了,才会执行协程块中的代码。
lifecycleScope
是什么# LifecycleOwner.kt
val LifecycleOwner.lifecycleScope: LifecycleCoroutineScope
get() = lifecycle.coroutineScope
通过调用链看到,它是lifecycle提供的一个扩展属性
:
val Lifecycle.coroutineScope: LifecycleCoroutineScope
get() {
while (true) {
//1.
val existing = mInternalScopeRef.get() as LifecycleCoroutineScopeImpl?
if (existing != null) {
return existing
}
//2.
val newScope = LifecycleCoroutineScopeImpl(
this,
SupervisorJob() + Dispatchers.Main.immediate
)
//3.
if (mInternalScopeRef.compareAndSet(null, newScope)) {
//4.
newScope.register()
return newScope
}
}
}
1.mInternalScopeRef
是lifecycle内部的一个属性:
AtomicReference<Object> mInternalScopeRef = new AtomicReference<>();
初次调用其get()
方法肯定是一个空的,所以会走到2处。
2.创建一个LifecycleCoroutineScopeImpl
对象,看下它是个啥:
可以看到这就是一个CoroutineScope
的子类,所以我们这样就创建了一个协程作用域对象
,并且指定:
SupervisorJob
,这样子job间发生异常而不会互相影响,阻止向上传递异常;Dispatchers.Main.immediate
,默认分发到主线程执行在这里顺便说下Dispatchers.Main.immediate
和Dispatchers.Main
的区别:
首先这两个都是指定把协程块内容分发到主线程中执行,但是前者多了个immediate,这其实是一种优化手段,我们看下官方文档怎么说:
简单说,如果创建协程块的线程和要指定的调度线程都是主线程,使用immediate
的就不需要额外使用分发器进行分发了,这算是一个优化小手段
。
3.将创建的这个协程作用域对象通过CAS
写入lifecycle的mInternalScopeRef
,这样当 lifecycleScope.launch
在此获取协程作用域就不会进行重复创建了,直接从mInternalScopeRef
获取即可。
综上所述, lifecycleScope
就是个协程作用域对象,用来在特定job和主线程中执行协程块代码逻辑。
4.注册观察者,当界面销毁时取消所有协程的执行
LifecycleCoroutineScopeImpl
本身就是观察者对象,所以看下register()
就是注册观察者:
fun register() {
launch(Dispatchers.Main.immediate) {
if (lifecycle.currentState >= Lifecycle.State.INITIALIZED) {
lifecycle.addObserver(this@LifecycleCoroutineScopeImpl)
} else {
coroutineContext.cancel()
}
}
}
同时LifecycleCoroutineScopeImpl
重写了onStateChanged()
方法:
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
if (lifecycle.currentState <= Lifecycle.State.DESTROYED) {
lifecycle.removeObserver(this)
coroutineContext.cancel()
}
}
就是为了方便当界面销毁了移除观察者,并取消所有的子协程代码块的执行,避免内存的泄漏。
之后还会有一篇文章介绍协程是如何绑定Activity的生命周期,即lifecycleScope.launchWhenXXX{}、lifecycle.repeatOnLifecycle(){}原理分析,了解两者的区别能帮助我们写出更加优雅的代码。
阅读量:1831
点赞量:0
收藏量:0