当前位置: 首页 > news >正文

jetpack之LiveData的原理解析

前言

在一通研究下,我打算LiveData的解析通过从使用的方法上面切入进行LiveData的工作原理分析😋。感觉这样子更能让大家伙理解明白,LiveData的实现和Lifecycle分不开,并且还得需要知道LiveData的使用会用到什么样的方法。所以,还不了解这两者的朋友可以看一下我之前写的博客

前置知识

jetpack之lifecycle的原理分析https://blog.csdn.net/i_xiang_la_shi/article/details/147191937?fromshare=blogdetail&sharetype=blogdetail&sharerId=147191937&sharerefer=PC&sharesource=i_xiang_la_shi&sharefrom=from_linkjetpack之LiveData的简单使用(特别简单,让你爽到飞!)https://blog.csdn.net/i_xiang_la_shi/article/details/147309717?fromshare=blogdetail&sharetype=blogdetail&sharerId=147309717&sharerefer=PC&sharesource=i_xiang_la_shi&sharefrom=from_link

LiveData的几个方法:

setValue:

虽然kotlin在使用LiveData的时候看似是直接赋值,其实是调用了setValue的方法。我们先来看setValue的源码:

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

通过代码我们可以观察到一个MainThred的注解,这说明setValue是一定要运行在主线程上的(也就是UI线程)。

mVersion是决定此事件是否为粘性事件的关键,如果mVersion>mLastVersion,那么就不是粘性事件,直接进行分发。

mData也就是数据了。

dispatchingValue看名字像是分发值,进入此方法,我们能发现他进行了一个遍历:

@SuppressWarnings("WeakerAccess") /* synthetic access */void dispatchingValue(@Nullable ObserverWrapper initiator) {if (mDispatchingValue) {mDispatchInvalidated = true;return;}mDispatchingValue = true;do {mDispatchInvalidated = false;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());if (mDispatchInvalidated) {break;}}}} while (mDispatchInvalidated);mDispatchingValue = false;}

dispatchingValue会遍历观察者列表,根据活跃状态和版本号决定是否分发数据(在considerNotify中有所体现)。

为什么我笃定它在setvalue中执行的时候就一定会遍历观察者列表呢?因为在setValue中他永远都发送的null,总会进入到else分支。

ObserverWrapper在后面的observe方法会简单讲一下

postValue:

接下来趁热打铁看一下postValue👌。

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

我们可以看到最后一行有一个postToMainThread的方法 。证明这个方法可以在子线程中运行,不过最终还是得去主线程。

点进这个Runnable参数看一下->

还是看最后一行:postValue最终还是通过setValue进行数据的修改。

所以,我们可以说,postValue通过 Handler 切换到主线程执行 setValue(),支持子线程更新

getValue:

看完setValue接着我们来看看getValue:

@Nullablepublic T getValue() {Object data = mData;if (data != NOT_SET) {return (T) data;}return null;}

好像就是一个获取data值的操作 😶

observer:

接下来是重头戏了,看看observer是怎么实现数据更新他就知道的:

@MainThreadpublic void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {assertMainThread("observe");if (owner.getLifecycle().getCurrentState() == DESTROYED) {// ignorereturn;}LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);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;}owner.getLifecycle().addObserver(wrapper);}

一样是运行在主线程的(这不废话),毕竟不在主线程也感知不到生命周期的变化😄

我们先看老熟人——ObserverWrapper

private abstract class ObserverWrapper {final Observer<? super T> mObserver;boolean mActive;int mLastVersion = START_VERSION;ObserverWrapper(Observer<? super T> observer) {mObserver = observer;}abstract boolean shouldBeActive();boolean isAttachedTo(LifecycleOwner owner) {return false;}void detachObserver() {}void activeStateChanged(boolean newActive) {if (newActive == mActive) {return;}// immediately set active state, so we'd never dispatch anything to inactive// ownermActive = newActive;changeActiveCounter(mActive ? 1 : -1);if (mActive) {dispatchingValue(this);}}}

在里面有几个关键的成员属性:mActivemLastVersion 。虽然只有一个avtivaStateChanged的方法,但是通过这个方法我们就能管中窥豹——LiveData在程序活跃的时候才会进行数据的观察和修改。

接下来我们再看LifecycleBoundObserver,Lifecycle也是老演员了,我们来看看这个Owner是怎么个事:

Overridepublic void onStateChanged(@NonNull LifecycleOwner source,@NonNull Lifecycle.Event event) {Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();if (currentState == DESTROYED) {removeObserver(mObserver);return;}Lifecycle.State prevState = null;while (prevState != currentState) {prevState = currentState;activeStateChanged(shouldBeActive());currentState = mOwner.getLifecycle().getCurrentState();}}

源码太多,但是这个方法像是鹤立鸡群那只鹤有,直接被我捕获到了哈哈哈(事实是抱着侥幸的心理查找了一下changed😜)

LifecycleBoundObserver看来就是告诉livedataOwner的生命周期改变了。

好了,大概就这么多

求关注

感觉主包讲的还可以可以给个关注😋

http://www.xdnf.cn/news/45883.html

相关文章:

  • 【25软考网工】第二章(8)差错控制、奇偶校验、CRC、海明码
  • Doris + Iceberg 构建冷热分层数据湖架构:架构设计与实战指南
  • Linux驱动开发--异步通知与异步I/O
  • 深度学习方向急出成果,是先广泛调研还是边做实验边优化?
  • ES6 第一讲 变量定义 堆与栈 字符串的扩展和数值型的扩展
  • c++STL——list的使用和模拟实现
  • 【题解-Acwing】790. 数的三次方根
  • 传导发射测试(CE)和传导骚扰抗扰度测试(CS)
  • 【概率论,算法】排列的峰值期望
  • seata db模式,nacos注册中心,spring boot ,spring cloud ,jdk1.8 完成的配置步骤
  • 【上位机——MFC】MFC入门
  • 状态管理最佳实践:Bloc架构实践
  • Android Jetpack Compose 状态管理解析:remember vs mutableStateOf,有啥不一样?为啥要一起用?
  • 【深度学习—李宏毅教程笔记】各式各样的 Attention
  • [原创](现代C++ Builder 12指南): [4]如何使用VCL的TStringBuilder?
  • IP数据报
  • kotlin,编码、解码
  • Navicat、DataGrip、DBeaver在渲染 BOOLEAN 类型字段时的一种特殊“视觉风格”
  • DSN主从同步
  • 【Linux】vim配置----超详细
  • 拼多多面经,暑期实习Java一面
  • 大数定理(LLN)习题集 · 题目篇
  • Java技术栈 —— 基本规范
  • [matlab]子图排版和线性回归
  • 基于Python智能体API的Word自动化排版系统:从零构建全流程模块化工作流与版本控制研究
  • MAC-QueryWrapper中用的exists,是不是用join效果更好
  • SpringBoot实战4
  • chili3d调试6 添加左侧面板
  • Linux学习——了解和熟悉Linux系统的远程终端登录
  • 架构师面试(三十四):IM 假在线