一.消息监听机制

来个例子

        data.observe(this, observer)data.setValue(1)

上述代码,监听者会触发一次,我们来看看其中的缘由

在setValue里会给mVersion 成员变量加一,意味着数据的版本 加一,这个mVersion默认值是-1

        mVersion++;mData = value;dispatchingValue(null);

然后追查dispatchingValue函数的调用链,看它 是如何通知到监听者, 因为当初传的是空,所以会执行else语句

            if (initiator != null) {considerNotify(initiator);initiator = null;} else {for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {considerNotify(iterator.next().getValue());}}

看看mObservers是什么,在 oberser函数里,把监听者和生命周期持有者封装存放在mObservers,所以遍历它来给所有注册的监听者传递最新的数据

        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);

这个considerNotify里,监听者有一个mLastVersion  成员变量,默认值是-1,与LiveData的mVersion相比较,如果大于等于mVersion,就表示数据版本更新,无需触发监听,否则就是把mVersion赋值给mLastVersion, 并且触发监听。

if (observer.mLastVersion >= mVersion) {return;}observer.mLastVersion = mVersion;observer.mObserver.onChanged((T) mData);

二.粘性消息机制

首先展示一个最简单能体现粘性消息的例子

        data.setValue(1)data.observe(this, observer)

上述代码依旧 能够触发监听者的回调,我们看看observe函数做了什么,把监听者 并和lifecycle持有者一起打包

        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);owner.getLifecycle().addObserver(wrapper);

找找 getLifecycle()获取的实例,我们需要从AppCompatActivity开始找,最后在FragmentActivity找到

    final LifecycleRegistry mFragmentLifecycleRegistry = new LifecycleRegistry(this);

然后来看看它的addObserver函数,它调用了这么一行代码,用于传递事件,继续追查

            statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));

给 封装了lifecycle持有者发送数据,看 mLifecycleObserver实例在哪

            mLifecycleObserver.onStateChanged(owner, event);

得继续 看 lifecycleEventObserver

        ObserverWithState(LifecycleObserver observer, State initialState) {mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);mState = initialState;}

这个判断很多,我 们需要 清楚这个observer的实例是啥

class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver
public interface GenericLifecycleObserver extends LifecycleEventObserver 

好了,我们再来看看lifecycleEventObserver 函数,说白了就是返回传进去的 实例了

        boolean isLifecycleEventObserver = object instanceof LifecycleEventObserver;if (isLifecycleEventObserver) {return (LifecycleEventObserver) object;}

然后看看onStateChanged函数调用了啥

activeStateChanged(shouldBeActive());

继续

                dispatchingValue(this);

还继续,这个函数就很眼熟了,里面进行了版本比较,和触发更新,

considerNotify(initiator);

三.setValue

首先说说setValue,它的元注解MainThread规定了此函数在主线程执行,赋值时,版本加一

    @MainThreadprotected void setValue(T value) {assertMainThread("setValue");mVersion++;mData = value;dispatchingValue(null);}

我再给出一个使用的例子,你们 猜猜,触发监听多少次,结果是一次,为何,我们接着看看  dispatchingValue函数

    override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)Log.v("zzw","onCreate")data.observe(this, observer)data.setValue(1)data.setValue(2)}

dispatchingValue最后会执行  considerNotify函数,这个函数虽然我之前贴出过几次,但没有说到它真正的厉害之处。

首先需要提醒的是 LiveData不只是一个简单的被监听者,它依赖于生命周期。

我在 if(!observer.mActive)这里打了断电,第一次 mActive为false,第二次为false,第三次为true。我调用了 两次setValue,为何有 三次调用到这里,说明还有其他 地方调用了。

    private void considerNotify(ObserverWrapper observer) {if (!observer.mActive) {return;}if (!observer.shouldBeActive()) {observer.activeStateChanged(false);return;}if (observer.mLastVersion >= mVersion) {return;}observer.mLastVersion = mVersion;//noinspection uncheckedobserver.mObserver.onChanged((T) mData);}

这里我对onStart和onResume都复写,打日志,再运行一次。这个说明第三次是在  onStart和onResume之间

onCreate
onStart
2
onResume

那我把 setvalue的代码放在onStart里,结果一样,如果放在onResume里,成功

onCreate
onStart
onResume
1
2

这里我再次打断点,considerNotify调用了三次,而且第一次因为LiveData的版本是-1,所以没有更新 数据。那这个多出的

一次调用是在onResume的开头。

首先我们看看,我们 在onStart和onCreate里的considerNotify调用是如何被中断的。因为前面打过断点,是因为observer.mActive为false,而这个变量默认没有赋值,也就是false,找找这个observer的 来源,来源是 LiveData.observer函数

        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);

这个observer的类是LifecycleBoundObserve,他有一个函数,看起来是分发状态,并且调用了父类的函数

        @Overridepublic void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {removeObserver(mObserver);return;}activeStateChanged(shouldBeActive());}

这里可以看出 mActive的值由传入的newActive决定,也就是 shouldBeActive函数决定

        void activeStateChanged(boolean newActive) {if (newActive == mActive) {return;}mActive = newActive;if (mActive) {dispatchingValue(this);}}

这个shouldBeActive函数实质内容就是, 判断当前宿主的生命周期是否大于等于 onStart,如果 是的就返回true

        @Overrideboolean shouldBeActive() {return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);}

所以我们之前的数据 传不到 监听者,是因为生命 周期不到。而每次生命周期变化,都会触发 onStateChanged函数

mLifecycleObserver.onStateChanged(owner, event);

setValue的总结:值传递到监听者,有生命周期的限制(onStart以上,onDestroy以下)并且每次生命周期变化都会试着将值传递给监听者。

四.postValue

postValue与setValue最大的 不同是,它可以在子线程传递数据。

而在子线程之间共享数据,最大的问题是线程同步,防止出现脏数据的问题

首先看看postValue,在同步锁下它先把 值传给 mPendingData,如果我们是连调用几个postValue, 因为当前mPendingData已经被赋值了,所以就被return了,看看 postToMainThread做了啥

    protected void postValue(T value) {boolean postTask;synchronized (mDataLock) {postTask = mPendingData == NOT_SET;mPendingData = value;}if (!postTask) {return;}ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);}

因为这是一个代理模式,我找找他的实现类

    private ArchTaskExecutor() {mDefaultTaskExecutor = new DefaultTaskExecutor();mDelegate = mDefaultTaskExecutor;}

使用创建了一个在主线程运行的Handler,来运行runable

    @Overridepublic void postToMainThread(Runnable runnable) {if (mMainHandler == null) {synchronized (mLock) {if (mMainHandler == null) {mMainHandler = new Handler(Looper.getMainLooper());}}}//noinspection ConstantConditionsmMainHandler.post(runnable);}

我们再回个头看看,运行的runable的内容,它把mPendingdata的值取出,然后赋予默认值,然后调用setValue。 这里需要 特别说明的是,之前也说过 连续调用几次postvalue, 只有第一次调用会 发送这个Runnable,但是这个 mPendingdata每次都会被赋值,所以这个节约了刷新次数。

    private final Runnable mPostValueRunnable = new Runnable() {@Overridepublic void run() {Object newValue;synchronized (mDataLock) {newValue = mPendingData;mPendingData = NOT_SET;}//noinspection uncheckedsetValue((T) newValue);}};

五.特殊情况解决

1.如果想让连续多次调用setValue,每次都触发更新,需要在onResume函数里调用

2.如果不想让分发LiveData设置的初始值,建议在设置初始值前,添加观察者

LiveData 机制详解相关推荐

  1. PHP autoload机制详解

    PHP autoload机制详解 转载自 jeakccc PHP autoload机制详解 (1) autoload机制概述 在使用PHP的OO模式开发系统时,通常大家习惯上将每个类的实现都存放在一个 ...

  2. 模糊匹配 读音_onenote搜索机制详解②:两种搜索模式,模糊与精确匹配

    先从纯文本搜索讲起,这是最基本也是最重要的. 从这篇开始,以及接下来连续几篇文章,都会介绍搜索的基础功能.注意,这几篇文章中谈论的都是基本的.正常的搜索功能,暂时不考虑Bug等因素. 在很多软件(例如 ...

  3. Java类加载机制详解【java面试题】

    Java类加载机制详解[java面试题] (1)问题分析: Class文件由类装载器装载后,在JVM中将形成一份描述Class结构的元信息对象,通过该元信息对象可以获知Class的结构信息:如构造函数 ...

  4. Numpy的广播机制详解(broadcasting)

    Numpy的广播机制详解(broadcasting) 广播(Broadcast)是 numpy 对不同形状(shape)的数组进行数值计算的方式, 对数组的算术运算通常在相应的元素上进行. 如果两个数 ...

  5. Session机制详解及分布式中Session共享解决方案

    Session机制详解及分布式中Session共享解决方案 参考文章: (1)Session机制详解及分布式中Session共享解决方案 (2)https://www.cnblogs.com/jing ...

  6. java异常处理机制详解

    java异常处理机制详解 参考文章: (1)java异常处理机制详解 (2)https://www.cnblogs.com/vaejava/articles/6668809.html 备忘一下.

  7. SpringMVC异常处理机制详解[附带源码分析]

    SpringMVC异常处理机制详解[附带源码分析] 参考文章: (1)SpringMVC异常处理机制详解[附带源码分析] (2)https://www.cnblogs.com/fangjian0423 ...

  8. 动态代理机制详解(JDK 和CGLIB,Javassist,ASM)

    2019独角兽企业重金招聘Python工程师标准>>> 在运行时期可以按照Java虚拟机规范对class文件的组织规则生成对应的二进制字节码.当前有很多开源框架可以完成这些功能,如A ...

  9. JAVA之JVM垃圾回收(GC)机制详解

    一.为什么需要垃圾回收 如果不进行垃圾回收,内存迟早都会被消耗空,因为我们在不断的分配内存空间而不进行回收.除非内存无限大,我们可以任性的分配而不回收,但是事实并非如此.所以,垃圾回收是必须的. 二. ...

最新文章

  1. js中Blob对象一般用法
  2. 电脑动态屏保_8款电脑软件,每一款都能让你的电脑更好用
  3. ElasticSearch各种查询对象Query的使用
  4. Windows高级编程学习笔记(一)
  5. 【转】20个让Web Developer开发生涯更加轻松的工具
  6. ORB-SLAM3论文解读
  7. [C#] TestHttpPost:测试Http的POST方法的小工具
  8. 华为交换机将端口由trunk更改为access报错解决方法
  9. JS 把 Wed Jul 15 2015 00:00:00 GMT+0800 转换成2015-07-15
  10. 【业务安全02】业务数据安全
  11. 软考2022下半年上午题真题和知识点整理
  12. matlab 正交多项式,常用正交多项式
  13. 【微信小程序源码】独立版云贝餐饮连锁V2_2.3.9源码线传小程序,新增堂食订单,支付打印新增下单时间显示
  14. JDP02-[策略模式]-鸭子模型
  15. Docker基础: Linux内核之Cgroups(1)
  16. 知觉:看到什么就是什么
  17. App开发中适用的短信SDK
  18. emoji表情在web html上显示
  19. 43、基于51单片机电子称16按键LCD 1602显示系统设计
  20. 【ML】基于机器学习的房价预测研究(系列7:双向LSTM模型)

热门文章

  1. EcoFlow正浩践行环保出行理念,为“低碳未来”助力
  2. 有了这几款软件,就不用纠结拍照识别植物的软件哪个好了
  3. 送小情人一个深海之声蓝牙耳机,樱花粉简直美得没朋友
  4. 阿里G2插件——柱状统计图,长变量值显示设置
  5. 自己动手写代码生成器
  6. latex编辑器的选择、texlive的安装及学位模板的使用
  7. 2017 最新qq登录算法
  8. 检测笔记本电脑的主板,cpu,硬盘的温度
  9. 怎么知道是否已经被好友删了微信?
  10. CSP 201809