上篇讲解了通过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对象,我们看下这个对象:
CoroutineLiveDatainternal 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()的实现,以及使用过程中的注意点。
阅读量:295
点赞量:0
收藏量:0