细说Jetpack中那些LiveData们

1.1)block代码块中的代码执行时机会执行多次吗?

  • block中的代码会在LiveData标为活跃状态后只执行,且正常情况下只会执行一次。LiveData的非活跃到活跃状态的切换发生在注册在其身上的活跃的observer从0变为1时。

  • 当因为LiveData的状态由活跃状态变为非活跃状态的时候,会发起取消掉代码块中的任务,但会有个时间间隔,超过了时间LiveData还未恢复活跃态时,会被取消掉。这个超时时间默认为5s。

  • 因为上述原因被取消掉的任务还会被重新执行。一旦执行成功了就不会再执行。

内部实现代码有删减只保留关键部分。

internal class CoroutineLiveData(

context: CoroutineContext = EmptyCoroutineContext,

timeoutInMs: Long = DEFAULT_TIMEOUT,

block: Block

) : MediatorLiveData() {

private var blockRunner: BlockRunner?

init {

val supervisorJob = SupervisorJob(context[Job])

val scope = CoroutineScope(Dispatchers.Main.immediate + context + supervisorJob)

//注释3.对象创建时会构建一个BlockRunner对象

blockRunner = BlockRunner( liveData = this,block = block,timeoutInMs = timeoutInMs, scope = scope)

{

blockRunner = null//注释4 最后一个参数是,此处会在代码块执行到末尾时执行。

}

}

override fun onActive() {

super.onActive()

blockRunner?.maybeRun() //注释5 活跃时尝试执行代码块,如果blockRunner为空就不会执行

}

}

internal class BlockRunner(…) {

private var runningJob: Job? = null

@MainThread

fun maybeRun() {

if (runningJob != null) return //注释7. 如果runningJob不为空也不会执行。

runningJob = scope.launch {

block(liveDataScope)//执行代码块

onDone()

}

}

}

  • 运行的代码块被包装在了BlockRunner内部类中,构造方法的最后一个参数会在代码块执行的最后的时候执行,也就意味着 blockRunner对象被置为null。当LiveData再次处于活跃状态时也不会执行了。

  • 一旦任务被取消成功注释8处,runningJob会被置空,注释5处 当LiveData重新处于活跃状态时block代码块就会被重新执行。

1.2)取消的超时机制怎么实现的?

BlockRunner

fun cancel() { //LiveData onInactive()时被调用

cancellationJob = scope.launch(Dispatchers.Main.immediate) {

delay(timeoutInMs) //注释10处

if (!liveData.hasActiveObservers()) {

runningJob?.cancel()

runningJob = null //注释11

}

}

}

fun maybeRun() {

cancellationJob?.cancel()//注释11

cancellationJob = null

runningJob?.cancel()

}

  • 开启一个取消协程任务,这个协程任务中首先有个等待,在等待期间注释10下面的逻辑就得不到执行。

  • 注释11处,如果当代码块执行之前,是否有取消任务,如果有会把这取消任务给终止掉

  1. 多面手MediatorLiveData

image.png

2.1) 用MediatorLiveData监听其他LiveData的数据变化。

  • MediatorLiveData # addSource(LiveData<S> source, Observer<? super S> onChanged) 当sourceLiveData数据有变化后,onChanged这个Observer会的onChange方法会被回调,我们可以在这个回调里选择向MediatorLiveData设置数据。

  • (思考,为啥onChanged这个参数的泛型声明为<? super S>,有什么含义。可参考另一篇文章 juejin.cn/post/702956…

  • public <S> void removeSource(LiveData<S> toRemote) 这个方法可以停止对某个LiveData的监听。

2.2) 内部实现

private static class Source implements Observer {

final LiveData mLiveData;

final Observer<? super V> mObserver;

int mVersion = START_VERSION;

void plug() { mLiveData.observeForever(this); }

void unplug() { mLiveData.removeObserver(this); }

@Override

public void onChanged(@Nullable V v) {

if (mVersion != mLiveData.getVersion()) {//会对比版本

mVersion = mLiveData.getVersion();

mObserver.onChanged(v);

}

}

}

  • 内部实现也比较简单,MediatorLiveData内部addSource方法会把LiveData和Observer包装成一个Source如上代码段。

  • Source实现了Observer,其onChanged方法中会有天剑的调用addSource方法传入的observer(onChanged)的方法。

最后的最后

对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!

当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的

最后,互联网不存在所谓的寒冬,只是你没有努力罢了!
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
应我们!**

当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的

[外链图片转存中…(img-nVjm6nLM-1715355183630)]

最后,互联网不存在所谓的寒冬,只是你没有努力罢了!
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

  • 21
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值