Android mvvm 之 LiveData 的原理

本文详细阐述了LiveData如何与LifecycleOwner建立订阅关系,强调了两者之间的激活状态和生命周期事件通知过程。特别是LiveData的值更新和LifecycleOwner的状态变化如何影响彼此,以及LifecycleRegistry在事件同步中的角色。
摘要由CSDN通过智能技术生成

return compareTo(state) >= 0;

}

}

进一步说明,只有当 LifecycleOwner 的状态是 STARTED 和 RESUMED 时,LiveData 才是处于激活状态的,而只有在激活状态下,LiveData 才会将最新数据变化通知给它的订阅者:

private void considerNotify(ObserverWrapper observer) {

if (!observer.mActive) { // 没有激活,不进行通知

return;

}

// 在 LifecycleOwner 的生命周期变化事件分派之前,需要提前主动更新一下激活状态,

// 如果未激活,同样不进行通知

if (!observer.shouldBeActive()) {

observer.activeStateChanged(false);

return;

}

//…省略非关键代码

observer.mObserver.onChanged((T) mData);

}

严格的说这里并不应该叫 LiveData 的激活状态,而应该是向 LiveData 进行订阅的 LifecycleOwner 的激活状态,此时 LifecycleOwner 作为观察者观察 LiveData 的变化。所以这里可能叫 LiveData 在每一个 LifecycleOwner 上的分身的激活状态更合适,为了表述方便,我们就统称叫 LiveData 的激活状态。我们将在 2.2 节描述 LifecycleOwner 如何订阅 LiveData。

以上,只为了说明一个问题:LiveData 需要订阅 LifecycleOwner,感知其生命周期变化:

livedata_observe_lifecycleowner

图示说明,LiveData 订阅 LifecycleOwner,而由 LifecycleOwner.Lifecycle 代理完成生命周期状态变化通知,所以 LiveData 直接能感知的是 Lifecycle。

2.2 LifecycleOwner 订阅数据变化

LifecycleOwner 在 STARTED 和 RESUMED 的状态下可以根据 LiveData 更新 UI 的状态,所以 LifecycleOwner 需要订阅 LiveData 的数据变化。

在实际实现当中,LifecycleOwner 作为抽象层并不具体负责订阅 LiveData,而是由业务层在 LifecycleOwner 中完成具体的订阅工作,此时我们称 LifecycleOwner 为 Controller 更合适,虽然它们往往是同一个东西:

lifecycleowner_observe_livedata

注意图示,一个 User-defined Observer 必须和一个 LifecycleOwner 唯一绑定,否则将无法订阅。试想,如果一个 Observer 同时绑定两个 LifecycleOwner:L1 和 L2,假如 L1 处于 RESUMED 的状态,而 L2 处于 DESTROYED 的状态,那么 LiveData 将无所适从:如果遵循 L1 的状态,将变化通知给 Observer,则更新 L2 会出错;如果遵循 L2 的状态,不将变化通知给 Observer,则 L1 得不到及时更新。

2.3 多对多的双向订阅网

LiveData 和 LifecycleOwner 之间因为需要相互观察对方状态的变化,从而需要实现双向订阅;同时,为了支持良好的可扩展能力,各自都维护了一个观察者列表,形成一个多对多的双向订阅网络:

bidirection_subscribes

我们看到一个 LiveData 是可以同时向多个 LifecycleOwner 发起订阅的,所以,LiveData 本身其实并不实际维护一个激活状态,真正的激活状态维护在 LifecycleOwner 的 User-defined observer 中。

3 LiveData 的事件变化

LiveData 值更新之后的需要通知订阅者(观察者),其通知流程非常简单:

livedata_setvalue

其中,判断观察者是否激活,即判断 LifecycleOwner 是否处于 STARTED 或 RESUMED 状态,在 2.1 节中已有说明。

我们看一下关键的源代码:

// 入口

@MainThread

protected void setValue(T value) {

// 必须在主线程调用

assertMainThread(“setValue”);

//…省略非关键代码

// 设置新值并派发通知

mData = value;

dispatchingValue(null);

}

// 通知派发流程

void dispatchingValue(@Nullable ObserverWrapper initiator) {

//…省略非关键代码

// 遍历观察者列表

for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =

mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {

// 尝试通知观察者

considerNotify(iterator.next().getValue());

//…省略非关键代码

}

}

其中 LiveData.considerNotify() 在 2.1 节中已有说明。

4 LifecycleOwner 的事件变化

对于 LifecycleOwner 来说,其变化的事件即为生命周期状态的变化。在 LifecycleOwner 的事件委托者 Lifecycle 看来,无论是发生了 ON_CREATE 事件还是 ON_START 事件,或是任何其它的事件,其事件的切换流程都是通用的。

换言之,只要 Lifecycle 接口的实现者实现这一通用切换流程,便只需给 LifecycleOwner 暴露一个切换入口,就能在 LifecycleOwner 的各个生命周期回调函数中调用这个入口就可以了。这样我们在 LifecycleOwner 中应该可以看到形如这样的流程(伪代码表示):

public class Activity/Fragment implements LifecycleOwner {

@Override

public onCrate() {

//…省略非关键代码

// 在 Jetpack 框架中,LifecycleImpl 被命名为 LifecycleRegistry

LifecycleImpl.handleLifecycleEvent(ON_CREATE);

}

@Override

public onStart() {

//…省略非关键代码

LifecycleImpl.handleLifecycleEvent(ON_START);

}

@Override

public onResume() {

//…省略非关键代码

LifecycleImpl.handleLifecycleEvent(ON_RESUME);

}

@Override

public onPause() {

//…省略非关键代码

LifecycleImpl.handleLifecycleEvent(ON_PAUSE);

}

@Override

public onDestroy() {

//…省略非关键代码

LifecycleImpl.handleLifecycleEvent(ON_DESTROY);

}

}

当然,在具体的源代码中,与上述伪代码会有一些出入,但是大体的结构是一致的。在 Jetpack 框架中,这个 Lifecycle 的实现者叫做 LifecycleRegistry。所以我们这里重点需要关注的就是 LifecycleRegistry 这个 Lifecycle 的代理接口的实现类是如何通知生命周期事件变化的。

4.1 Lifecycle 接口的实现——LifecycleRegistry
4.1.1 LifecycleRegistry 的订阅实现

如 2.2 节所述,通过 LiveData.observe(owner, user-defined observer),LifecycleOwner 的业务层向 LiveData 订阅数据变化,而在 LiveData.observe() 方法内,同时会自动通过 Lifecycle.addObserver(LiveData-defined observer) 向 LifecycleOwner 订阅生命周期变化:

// LiveData.observe()

@MainThread

public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {

//…省略非关键代码

LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);

//…省略非关键代码

// 向 LifecycleOwner 发起订阅

owner.getLifecycle().addObserver(wrapper);

}

以上方法内的 owner.getLifecycle() 的实际对象即为 LifecycleRegistry,我们来看一下 LifecycleRegistry.addObserver() 的基本订阅流程:

lifecycleregistry_addobserver.png

从整个流程来看,总体可以分为三步:

  • 第一步是初始化观察者对象的状态,并将观察者缓存入队;

  • 第二步是以模拟派发生命周期事件的形式,将新加入的观察者的状态提升到目前为止可提升的最大状态;

  • 第三步是同步所有观察者的状态到全局状态。

我们可以看到,最后所有的观察者的状态都要同步到全局状态,全局状态即为 LifecyclerOwner 最新的状态。那么为什么需要进行这么繁琐的逐步模拟派发事件来进行同步呢?直接一步到位不行么?

我们可以考虑一个生命周期感知组件 LifeLocation,其功能是用于进行定位,它订阅了 LifecycleOwner,我们假设 LifeLocation 需要在 CREATED 的时候进行一些必要的初始化,而在 STARTED 的时候开始执行定位操作。假如在 LifecycleRegistry 中的状态同步可以一步同步到全局状态,那么有可能当前的全局状态已经是 RESUMED 的了,这样 LifeLocation 既得不到初始化,也无从启用定位功能了。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(资料价值较高,非无偿)

最后

现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水!

为什么某些人会一直比你优秀,是因为他本身就很优秀还一直在持续努力变得更优秀,而你是不是还在满足于现状内心在窃喜!

Android架构师之路很漫长,一起共勉吧!

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

jpg" />

最后

现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水!

为什么某些人会一直比你优秀,是因为他本身就很优秀还一直在持续努力变得更优秀,而你是不是还在满足于现状内心在窃喜!

Android架构师之路很漫长,一起共勉吧!

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值