上篇讲解了通过liveData{}创建CoroutineLiveData的基本使用,本篇文章主要介绍CoroutineLiveData的原理分析,这是一个基于协程+MediatorLiveData实现的一种build构建livedata的类。
肢解LiveData:协程味的CoroutineLiveData了解一下(一)
liveData{}
入口分析public fun <T> liveData(
context: CoroutineContext = EmptyCoroutineContext,
timeoutInMs: Long = DEFAULT_TIMEOUT,
@BuilderInference block: suspend LiveDataScope<T>.() -> Unit
): LiveData<T> = CoroutineLiveData(context, timeoutInMs, block)
实际上创建了一个CoroutineLiveData
对象,我们看下这个对象:
CoroutineLiveData
internal class CoroutineLiveData<T>(
context: CoroutineContext = EmptyCoroutineContext,
timeoutInMs: Long = DEFAULT_TIMEOUT,
block: Block<T>
) : MediatorLiveData<T>()
这个类继承了MediatorLiveData
,这就为emitSource()
的实现埋下了伏笔,稍后分析。MediatorLiveData
有两个很关键的属性:
接下来我们从MediatorLiveData
的方法onActive()
作为入口进行分析。
onActive()
override fun onActive() {
super.onActive()
blockRunner?.maybeRun()
}
这个方法大家很熟悉,就是当界面状态大于Started
时就会被回调执行,该方法会调用到blockRunner
的maybeRun()
方法:
BlockRunner.maybeRun()
@MainThread
fun maybeRun() {
//省略
runningJob = scope.launch {
val liveDataScope = LiveDataScopeImpl(liveData, coroutineContext)
block(liveDataScope)
onDone()
}
}
请注意scope协程作用域指定的调度器为Dispatchers.Main.immediate,所以说liveData{}中的代码块会默认在主线程中执行。
LiveDataScopeImpl
对象,我们在liveData{}
中调用emit()
和emitSource()
方法都是来自于它:2.调用block(liveDataScope),这个block就是liveData{}中代码块;
3.当代码块执行完毕就会执行传入onDone(),将CoroutineLiveData的blockRunner置null,看可以说是非常的严禁了。
接下来我们来一一看下emit()
和emitSource()
的实现。
LiveDataScopeImpl.emit()
override suspend fun emit(value: T) = withContext(coroutineContext) {
target.clearSource()
target.value = value
}
这个target
对象就是我们创建的CoroutineLiveData
:
LiveDataScopeImpl.emitSource()
override suspend fun emitSource(source: LiveData<T>): DisposableHandle =
withContext(coroutineContext) {
return@withContext target.emitSource(source)
}
最终调用CoroutineLiveData.
的emitSource()
方法。
CoroutineLiveData.emitSource()
internal suspend fun emitSource(source: LiveData<T>): DisposableHandle {
clearSource()
val newSource = addDisposableSource(source)
emittedSource = newSource
return newSource
}
internal suspend fun <T> MediatorLiveData<T>.addDisposableSource(
source: LiveData<T>
//1.
): EmittedSource = withContext(Dispatchers.Main.immediate) {
//2.
addSource(source) {
value = it
}
//3.
EmittedSource(
source = source,
mediator = this@addDisposableSource
)
}
2.调用 MediatorLiveData
的addSource()
方法添加数据源监听:
这个方法大家应该很熟悉了,这个source
参数就是通过emitSource()
方法的参数传入的。我们简单看下addSource()
方法的实现:
Source类的创建:
本篇文章分析了liveData{}
的实现原理,核心在emit()
和emitSource()
的实现,以及使用过程中的注意点。
阅读量:270
点赞量:0
收藏量:0