Android Jetpack之LiveData源码分析
创始人
2024-02-11 07:57:16
0

LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 activity、fragment 或 service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。

如果观察者(由 Observer 类表示)的生命周期处于 STARTED 或 RESUMED 状态,则 LiveData 会认为该观察者处于活跃状态。LiveData 只会将更新通知给活跃的观察者。为观察 LiveData 对象而注册的非活跃观察者不会收到更改通知。

您可以注册与实现 LifecycleOwner 接口的对象配对的观察者。有了这种关系,当相应的 Lifecycle 对象的状态变为 DESTROYED 时,便可移除此观察者。这对于 activity 和 fragment 特别有用,因为它们可以放心地观察 LiveData 对象,而不必担心泄露(当 activity 和 fragment 的生命周期被销毁时,系统会立即退订它们)。

LiveData 的优势:

  • 确保界面符合数据状态
  • 不会发生内存泄漏
  • 不会因 Activity停止而导致崩溃
  • 不再需要手动处理生命周期
  • 数据始终保持最新状态
  • 适当的配置更改
  • 共享资源

以上内容均来自官网,官网地址

在这里插入图片描述
通过之前的博客:LiveData的简单使用。我们了解了LiveData的基本使用。这里回顾一下

LiveData的简单实用(一般都是跟ViewModel一起实用)


public class LiveDataActivity extends AppCompatActivity {private TextView mTextContent;//使用LiveDataprivate MutableLiveData contentLiveData = new MutableLiveData<>();@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_livedata_test);mTextContent = findViewById(R.id.tv_content);//设置 观察者contentLiveData.observe(this, new Observer() {@Overridepublic void onChanged(String s) {mTextContent.setText(s);}});//点击按钮,改变内容findViewById(R.id.btn_livedata_change).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {contentLiveData.setValue("内容改变了");}});}
}

下面的源码分析中,有些情况会设计到Lifecycle()监控生命周期。有兴趣的可以看下:Android Jetpack之Lifecycle的使用及源码分析

下面,我们通过上面使用的步骤,来分析。LiveData内容都做了什么操作

  • 一、分析观察者LiveData#observe方法
  • 二、分析通过set/postValue 方法改变内容

一、设置observe()方法

添加观察者,并且我们无需关系,移除及内存泄露问题

下面看下源码

private SafeIterableMap, ObserverWrapper> mObservers =new SafeIterableMap<>();...@MainThreadpublic void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {assertMainThread("observe");//owner是Activity已经实现的(Lifecycle文章有说)//如果owner的生命周期已经结束的话,直接返回。避免了内存泄露,甚至Crashif (owner.getLifecycle().getCurrentState() == DESTROYED) {// ignorereturn;}//wrapper包装类。里面主要是一些生命周期及版本的判断LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);//这里,我们看到添加观察者的时候。是把观察者做key,放到了一个Map里面ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);if (existing != null && !existing.isAttachedTo(owner)) {throw new IllegalArgumentException("Cannot add the same observer"+ " with different lifecycles");}if (existing != null) {return;}//这里跟我们添加Lifecycle()一样,可以让wrapper监听owner生命周期,做一些判断owner.getLifecycle().addObserver(wrapper);}

看到这里,其实发现很简单,添加观察者,其实,就是在LiveData里面创建了一个Map,把观察者存进去。

Map的值是个包含了owner(这里就是Activity,方便理解)和观察者observer的封装类。

二、分析通过set/postValue()改变内容

下面,我们看看LiveData的setValue()方法,是怎么把值传递过去的

public class MutableLiveData extends LiveData {@Overridepublic void setValue(T value) {super.setValue(value);}
}

这里调用了super.setValue()继续看

    @MainThreadprotected void setValue(T value) {assertMainThread("setValue");//这里的版本,后面会说mVersion++;mData = value;dispatchingValue(null);}

这里做了2个事情:

1,把值赋值给mData
2,调用 dispatchingValue(null);

我们接着看下

  void dispatchingValue(@Nullable ObserverWrapper initiator) {if (mDispatchingValue) {mDispatchInvalidated = true;return;}mDispatchingValue = true;do {mDispatchInvalidated = false;//initiator这里通过上面知道,传递的是null。所以,走elseif (initiator != null) {considerNotify(initiator);initiator = null;} else {//把所有观察者的Map,通过迭代器遍历for (Iterator, ObserverWrapper>> iterator =mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {considerNotify(iterator.next().getValue());if (mDispatchInvalidated) {break;}}}} while (mDispatchInvalidated);mDispatchingValue = false;}

这里,我们可以看到,dispatchingValue()方法就是,遍历观察者所在的Map,然后,调用considerNotify()方法。

看下considerNotify()方法

 private void considerNotify(ObserverWrapper observer) {if (!observer.mActive) {return;}// Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.//// we still first check observer.active to keep it as the entrance for events. So even if// the observer moved to an active state, if we've not received that event, we better not// notify for a more predictable notification order.if (!observer.shouldBeActive()) {observer.activeStateChanged(false);return;}if (observer.mLastVersion >= mVersion) {return;}observer.mLastVersion = mVersion;//通过上面一系列的判断,最终调用了观察者的onChanged方法。observer.mObserver.onChanged((T) mData);}

这里,我们可以看到通过一些列生命周期的判断,版本的判断,最终调用了观察者的onChange()方法。
到这里,我们就已经走通了,所有的调用流程。

postValue的全过程跟setValue类似。只不过是后面通过Handler切换到了主线程上

在这里插入图片描述

[未完成]
上面有一点东西,我们没有说,那就是观察者observer的mLastVersion跟数据的mVersion问题。这个也是造成粘性数据的原因。但是,它跟EventBus不同的是,EventBus是提供了粘性数据的开关,但是,它并没有。

问题:LiveData的数据倒灌/粘性数据问题。

场景:(列表–详情(修改数据)–返回并点击其它列表–再次进入详情)(使用ShareViewModel)

SingleLiveEvent(解决一次事件,只消费一次),当注册多个观察者后,只有一个会受到,非常容易出错。

UnPeek-LiveData 解决方案

相关内容

热门资讯

描写西湖美景的句子   描写西湖美景的句子  1、在这里,自然与人的创造融为一体,相得益彰,自然的美,伦理的美综合为美的...
东西丢了的难过句子精选380... 东西丢了的难过句子 精选88句1. 失踪的爱人,其实从来不曾真正地属于你,不必可惜。2. 同事去见客...
形容美的诗句 形容美的诗句(精选85句)  在平平淡淡的日常中,大家总免不了要接触或使用诗句吧,诗句是组成诗词的句...
一年级描写春天的句子短句 一年级描写春天的句子汇编送给大家,每一句都是小编精选的,欢迎阅读,希望能在写作上给大家带来帮助。喜欢...
描写树木的好段 描写树木的好段  导语:一株马尾松挺拔地长在山坡上,它那粗壮的枝丫,像有力的手臂一样,横伸在湛蓝的晴...
古风虐心凄美句子 古风虐心凄美句子  山河拱手,为君一笑。  来生我再来典当来世我再来与你歃血为盟。  相见得恨晚,相...
早安唯美句子 早安唯美句子(精选125句)  在日常学习、工作和生活中,大家都经常接触到句子吧,句子可分为单句和复...
等待下次相聚的完整句子怎么说... 等待下次相聚的完整句子怎么说 精选137句1. 莱佛士酒店美景,返京了,期待下一次相遇,时尚与文化的...
如何背诵课文 如何背诵课文首先要理解课文,如何背诵课文。一篇课文,你可先预习,借助词典弄清每个单词和词组的'意义,...
描写溪水的句子 描写溪水的句子  在平平淡淡的学习、工作、生活中,大家都收藏过令自己印象深刻的句子吧,句子可分为单句...
表达想家的优美句子精选150... 表达想家的优美句子 精选118句1. 陈星唱的《离家的孩子》很经典,其中一句是“离家的孩子夜里又难眠...
跨年感慨朋友圈句子 跨年感慨朋友圈句子  在日常学习、工作或生活中,说到句子,大家肯定都不陌生吧,不同的句子在语言环境中...
向国旗敬礼优美句子 向国旗敬礼优美句子大全  国庆即将来临,我作为一名在国旗下长大的少先队员,祝福祖国母亲的六十八岁生日...
人生很失败的句子精选485句 人生很失败的句子 精选40句1. 我可以戒掉抽了这么久的烟,却忘不了爱了这么久的你。2. 人生有些事...
描写花的佳句   描写花的佳句  1、满地芦花和我老,归家燕子傍谁飞。  2、月季花的枝叶是绿油油的,上面有许多又...
感谢老板发红包的句子 感谢老板发红包的句子  在日复一日的学习、工作或生活中,大家都接触过比较经典的句子吧,从句法角度说,...
通用早安共勉句子语录 通用早安共勉句子语录锦集30条  老虎不发威他就一只病猫!发威了他就是王者!所以人人都可以是王者但同...
失去你的那一天句子精选35句 失去你的那一天句子 精选35句1. 你走了,留给我的是无尽的思念。但,即使再不能见到你,有这份真情伴...
最好的告别经典句子 最好的告别经典句子(精选230句)  在平日的学习、工作和生活里,许多人都接触过一些比较经典的句子吧...
西游记精彩语句摘抄 西游记精彩语句摘抄大全  导语:相信很多人都有看过西游记的,那么你对里面哪些精彩句子印象最深刻呢?下...