owner.getLifecycle().addObserver(wrapper);
}

observe方法传有两个参数LifecycleOwner和Observer,LifecycleOwner是一个具有Android生命周期的类,一般传入的是Activity和Fragment,Observer是一个接口,内部存在void onChanged(T t)方法。

✅ 第一部分: observe内部一开始就存在一个生命周期的判断,

if (owner.getLifecycle().getCurrentState() == DESTROYED) {return;}

当组件生命周期已经Destroy了,也就没有必要再继续走下去,则直接return。在这里,LiveData对生命周期的感知也就慢慢显现出来了。

✅ 第二部分: 首先以LifecycleOwner和Observer作为参数创建了一个LifecycleBoundObserver对象,接着以Observer为key,新创建的LifecycleBoundObserver为value,存储到mObservers这个map中。在后面LiveData postValue中会遍历出该map的value值ObserverWrapper,获取组件生命周期的状态,已此状态来决定分不分发通知(这部分详情见“第二小节postValue()”)

那LifecycleBoundObserver是什么?

class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mOwner;

LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}


}

从源码可以看到,LifecycleBoundObserver继承ObserverWrapper并且实现了LifecycleEventObserver的接口,LifecycleEventObserver是监听组件生命周期更改并将其分派给接收方的一个接口,而在LifecycleBoundObserver的构造函数中将observer传给了父类ObserverWrapper。LifecycleBoundObserver其实只是包裹着LifecycleOwner和Observer得一个类,其中的实现有点代理模式的味道。

✅ 第三部分: owner.getLifecycle().addObserver(wrapper)将新创建的LifecycleBoundObserver添加到Lifecycle中,也就是说这个时候观察者注册成功,当LifecycleOwner也就是组件的状态发生改变时,也会通知到所匹配的observer。

到这里,UI层viewModel.liveData.observe(this, object:Observer<String> { override fun onChanged(value: String) {} })注册观察者的内部解析也就大致清楚了。

2.postValue()

liveData.postValue()是作为一个发射方来通知数据改变,其内部又做了哪些工作?接下来就一探究竟。直接从postValue中最核心的部分在于将参数value赋值给了一个全局变量源码开始:

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

postValue中首先将参数value赋值给了一个全局变量mPendingData,它的初始值为一个空对象,而mPendingData只是作为一个中间媒介来存储value的值,在后续的操作中会用到,我们就暂时先记住它。

在最后就是一个将线程切换到主线程的操作,主要看mPostValueRunnable的实现:

private final Runnable mPostValueRunnable = new Runnable() {
@SuppressWarnings(“unchecked”)
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
setValue((T) newValue);
}
};

在Runnable中,mPendingData赋值给了临时变量newValue,最后调用了setValue()方法。我们都知道LiveData发送通知可以使用PostValue或者SetValue,而他两的区别就在于,PostValue可以在任意线程中调用,而SetValue只能在主线程中,因为PostValue多了一步上面切换主线程的操作。

OK,接下来就是PostValue/SetValue最核心的部分。

@MainThread
protected void setValue(T value) {
assertMainThread(“setValue”);
mVersion++;
mData = value;
dispatchingValue(null);
}

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;
}

在setValue中,参数value将值赋给了一个全局变量mData,而这个mData最后将通过mObserver.onChanged((T) mData);将需要修改的value值分发给了UI。最后调用传入一个null调用dispatchingValue方法。

由于dispatchingValue里的参数为null,也就顺理成章的走到了✅ 第二部分。else一进入就是迭代器在遍历mObservers,而mObservers在第一小节“1.LiveData.observe()”中说得很清楚,它作为一个map,存储了Observer和ObserverWrapper。通过遍历,将每个观察者所匹配的ObserverWrapper作为参数传给了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 o

《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享

bserver 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;
observer.mObserver.onChanged((T) mData);
}

而在considerNotify()中,先通过observer来获取组件生命周期的状态,如果处于非活动状态,则拒绝发起通知。在该方法的最后, observer.mObserver.onChanged((T) mData),是不是很熟悉,这就是UI层一开始就实现的接口,而就在这找到了最后的发送方。

小结

LiveData是如何通信的?就一句话,UI层注册好一个observer,就存储到一个存储着观察者的map中,直到开发者调用postValue/setValue则遍历该map,分发出observer的onChanged通知,在此过程中,都会监听组件的生命周期,并以此来判断所匹配的组件是否处于活动状态,否则直接return。

三、LiveData的粘性事件

发送消息事件早于注册事件,依然能够接收到消息的通知的为粘性事件

即先调用LiveData的postValue/setValue方法,后注册observe,依然能够收到onChange()的通知。从上面的分析可以知道,LiveData最后postValue是将通知分发给已经注册好的观察者,而LiveData的粘性事件是先发送后注册,那为什么也能够收到通知呢?是哪里分发了onChange()?

我们知道粘性事件是注册后就收到了通知,那么就可以以liveData.observe()为切入点,康康源码中的实现。

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

owner.getLifecycle().addObserver(wrapper);
}

LiveData注册观察者,最核心在于owner.getLifecycle().addObserver(wrapper);addObserver是用来添加一个LifecycleObserver,当LifecycleOwner改变状态时,它会被通知。例如,如果LifecycleOwner处于State#STARTED状态,给定的观察者将收到Event#ON_CREATE、Event#ON_START事件。

而我们跟踪到它的实现类里面,

public class LifecycleRegistry extends Lifecycle {

@Override
public void addObserver(@NonNull LifecycleObserver observer) {
State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);

if (previous != null) {
return;
}
LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
if (lifecycleOwner == null) {
// it is null we should be destroyed. Fallback quickly
return;
}

boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
State targetState = calculateTargetState(observer);
mAddingObserverCounter++;
while ((statefulObserver.mState.compareTo(targetState) < 0
&& mObserverMap.contains(observer))) {
pushParentState(statefulObserver.mState);
✅ 切入点
statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
popParentState();
// mState / subling may have been changed recalculate
targetState = calculateTargetState(observer);
}


}
}

LifecycleRegistry继承了Lifecycle,是一个处理多个观察者的类,在这个类中的addObserver方法有一个被我标记✅切入点 statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState)),dispatchEvent表示将ON_CREATE、ON_START等事件分发给观察者,以达到监听生命周期的作用。在dispatchEvent方法中,LifecycleEventObserver通过onStateChanged接口分发给了相应的观察者,如下:

void dispatchEvent(LifecycleOwner owner, Event event) {
State newState = getStateAfter(event);
mState = min(mState, newState);
✅ 切入点
mLifecycleObserver.onStateChanged(owner, event);
mState = newState;
}

看到mLifecycleObserver.onStateChanged(owner, event)是不是有种熟悉的感觉,其实在第二节源码分析中,类LifecycleBoundObserver就实现了LifecycleEventObserver接口,并重写了onStateChanged方法。

class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mOwner;

LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}

,

@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
✅ 切入点
activeStateChanged(shouldBeActive());
}


}

如果当前生命周期状态处于DESTROYED,则将观察者从列表中移除,防止内存泄漏,接着就调用了activeStateChanged方法。

void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
// immediately set active state, so we’d never dispatch anything to inactive
// owner
mActive = newActive;
boolean wasInactive = LiveData.this.mActiveCount == 0;
LiveData.this.mActiveCount += mActive ? 1 : -1;
if (wasInactive && mActive) {
onActive();
}
if (LiveData.this.mActiveCount == 0 && !mActive) {
onInactive();
}
✅ 切入点
if (mActive) {
dispatchingValue(this);
}
}

在 ✅ 切入点之前代码不需要多看,只是一些判断当前活动是否活跃的一起逻辑,核心在于dispatchingValue(this),看到这个方法,是不是又感觉到一丝熟悉,如果看了第二节的分析,就会发现第二节setValue()中也调用了一句dispatchingValue(null),只不过setValue传入的是null,而现在这里传入了一个this值。接下啦就来看看传如参数和null有什么不同?

void dispatchingValue(@Nullable ObserverWrapper initiator) {

do {
mDispatchInvalidated = false;
if (initiator != null) {
✅切入点1
considerNotify(initiator);

【Jetpack篇】LiveData取代EventBus,安卓面试项目相关推荐

  1. 【Jetpack篇】LiveData取代EventBus,flutter安装

    //请求数据成功后,通知UI刷新界面 updateUI() } }) //请求数据 viewModel.loadData() } } 上面三层基本上就是一个网络请求的闭环,Repository负责从网 ...

  2. 实现马蜂窝旅游头像泡泡动画,安卓面试项目经验

    if (null != browseEntity) { roundedImageView.setBackgroundResource(browseEntity.drawableId); String ...

  3. LiveData vs EventBus?不,他们其实可以一起

    /   今日科技快讯   / 近日,据国外媒体报道,电动汽车厂商特斯拉的股价本周一再次大涨,延续上周4个交易日连续大涨的势头,CEO埃隆·马斯克的身价也因此而增至463亿美元,比马云和拼多多创始人黄峥 ...

  4. 【12.2~12.6周报】面试项目搭建,红黑树,个人线上事故

    你知道的越多,你不知道的越多 温故知新,本周精选文章回顾 : 暖男提醒:点击标题即可阅读 <浅入浅出>-RocketMQ 这篇文章,说实话是真的长,也是我目前唯一一篇纯技术类型的文章,之前 ...

  5. 2022华为Android面试真题,腾讯安卓面试

    一.java相关 java基础 1.java 中==和 equals 和 hashCode 的区 <Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义> An ...

  6. C#使用Xamarin开发可移植移动应用进阶篇(8.打包生成安卓APK并精简大小),附源码...

    C#使用Xamarin开发可移植移动应用进阶篇(8.打包生成安卓APK并精简大小),附源码 原文:C#使用Xamarin开发可移植移动应用进阶篇(8.打包生成安卓APK并精简大小),附源码 前言 系列 ...

  7. python面试项目案例

    1.python第三方模块下载 2.scrapy框架爬虫 3.python使用matplotlib模块绘制折线图相关参数 4.numpy读取本地数据 5.lambda函数用法 6. list,sort ...

  8. 安卓开源项目(最近准备撸安卓)

    经常有人问我有没有什么项目代码,我回复说去 Github 找,但是还是好多人不知道如何找到那些比较好的项目. 今天花了点时间找了些安卓的项目,觉得还是不错的,几乎就是自己生活常用的一些 app ,如果 ...

  9. Android小技巧,快手安卓面试

    工欲行其事,必先利其器 1.B4A B4A是Android的基础版,这是一种可简化编程的Android的应用程序开发工具.这是一个IDE,可以允许开发者使用Basic语言来创建Android移动应用. ...

最新文章

  1. 欧拉函数的求法(线性筛法?)
  2. 使用java代码代替xml实现SSM
  3. 寻找两个字符串相似度的代码
  4. [总结篇3]Provider_network的含义
  5. 中国水闸橡胶密封件市场需求状况与营销模式建议报告2022年
  6. 多个项目怎么配置到服务器上,多个项目怎么配置到服务器
  7. linux 上plsql命令_在 Linux 上压缩文件:zip 命令的各种变体及用法 | Linux 中国
  8. JavaScript 变量及数据类型
  9. 数据结构与算法python—10.二叉树题目leetcode总结
  10. Json对象和Json字符串的区别
  11. SWF也能修改!硕思闪客精灵专业Flash反编译工具
  12. 014吸管工具,颜色取样器工具,标尺工具和注释工具
  13. 计算机电子报模板,计算机辅助电气电子线路设计课程设计设计报告排版模板(WIT).doc...
  14. pandas+pyecharts实现交互式K线行情展示,高颜值日线+分时图,自动获取行情信息
  15. 【Web开发】Python实现Web图表功能(D-Tale入门)
  16. Javascript特效:五彩小球
  17. JavaScript数据类型 1
  18. 亚马逊广告投放策略卖家们知多少?
  19. 当没有接口文档时候,测试人员如何测试?
  20. 二见钟情之SQL语句嵌套查询

热门文章

  1. 星上维智能科技CEO左作人,机器视觉会越来越智能化
  2. 完善跨境金融区块链服务平台,支持区域开放创新和特殊区域建设
  3. 哪几款蓝牙耳机好用?2022年最值得买的十款蓝牙耳机盘点
  4. 辉光管升压电路理论,让USB升压170V
  5. 一条狗的死亡,引发3亿网友愤怒!希望这条黑科技 “汪星人” 能从小培养人的爱心 | 钛空智慧星球推荐
  6. iOS图像最佳实践总结
  7. 红米note2报告android,红蓝之争 魅蓝Note 2/红米Note对比评测
  8. 切比雪夫不等式例题讲解_2019高考数学大题押题(名师视频讲解,高考最后的提分机会)...
  9. 以【?nid=】的形式进行页面的跳转
  10. EVT、PVT、DVT