【AAC 系列三】深入理解架构组件:LiveData

  1. 通过 setValue()/postValue() 更新数据的处理流程是如何?
  2. 生命周期变化后数据处理流程是怎么样的?

同时提前看下我整理的 LiveData UML 图,对 LiveData 有个整体的了解,后续的涉及到的类都在这里了,有助于理解。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

(图1.LiveData 类图)

OK, here we go!

2.1 LiveData.observe()

LiveData 的使用流程从 observe() 开始,咱们尝试从 observe() 方法 开始分析:

@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
//如果是 DESTROYED 的状态则忽略
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
//把 Observer 用 LifecycleBoundObserver 包装起来
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
//缓存起来
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
//如果已经 observe 过 并且两次的 owner 不同则报错
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException(“Cannot add the same observer”

  • " with different lifecycles");
    }
    if (existing != null) {
    return;
    }
    //绑定 owner
    owner.getLifecycle().addObserver(wrapper);
    }

可以看到 observe 方法里把我们传递的 observer 用 LifecycleBoundObserver  包装了起来,并且存入了 mObservers  ,并且跟 owner 进行了关联。

并且做了两个特殊处理:

  1. 忽视处于 DESTROYED 的 owner 的注册行为
  2. 将一个 Observer 同时绑定两个 owner 的行为视为非法操作,也即一个 Observer 只能绑定一个 owner,而 owner 可以有多个 Observer;

这里出现了几个新的类 LifecycleBoundObserverObserverWrapper 来看看。

2.2 LifecycleBoundObserver

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

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

@Override
boolean shouldBeActive() {
// 判断 owner 当前的状态是否是至少 STARTED
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}

@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
//生命周期改变,如果是 DESTROYED 就自动解除
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
//ObserverWrapper.activeStateChanged
activeStateChanged(shouldBeActive());
}

@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}

@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}

**ObserverWrapper **:

private abstract class ObserverWrapper {
final Observer mObserver;
boolean mActive;
int mLastVersion = START_VERSION;

ObserverWrapper(Observer observer) {
mObserver = observer;
}
//是否是 active 状态
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
// 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();
}
//如果 active 状态下,则发送数据更新通知
if (mActive) {
dispatchingValue(this);
}
}
}

仔细看下这两个类其实就能解答疑问了。

LifecycleBoundObserver 是 抽象类 ObserverWrapper 的子类,重写了 shouldBeActive() 方法,在 owner 处于至少是 STARTED 的状态下认为是 active 状态;并且它也实现了 GenericLifecycleObserver 接口,可以监听 lifecycle 回调,并且在 onStateChanged() 方法里处理了生命周期改变的事件,当接收到 DESTROYED 的事件会自动解除跟 owner 的绑定,并且将下个流程交给了 activeStateChanged() 。

到这里 【2.1】、【2.3】的问题已经有了答案:

【2.1】答:LifeData 在 observe 方法中用 LifecycleBoundObserver 包装了 observer ,并且通过它绑定了owner。
【2.3】答:LifecycleBoundObserver 在 onStateChanged() 方法里处理了生命周期改变的事件,当接收到 DESTROYED 的事件会自动解除跟 owner 的绑定。

这里需要注意的是,当我们调用 observe() 注册后,由于绑定了 owner,所以在 active 的情况下,LiveData 如果有数据,则 Observer 会立马接受到该数据修改的通知。

此时的流程是:

observe–>
onStateChanged–>
activeStateChanged–>
dispatchingValue–>
considerNotify–>
onChanged

可以称之为生命周期改变触发的流程,另外还有一种流程是 postValue&setValue 触发的流程,共两种。

2.3 activeStateChanged(boolean)

在 activeStateChanged() 方法里,处理了 onActive() 跟 onInactive() 回调的相关逻辑处理,并且调用了dispatchingValue(this) 。(MediatorLiveData 用到了 onActive() 跟 onInactive() 有兴趣自行了解,这里不展开)

接下去探索 dispatchingValue

2.4 dispatchingValue(ObserverWrapper) 分析

private void dispatchingValue(@Nullable ObserverWrapper initiator) {
//如果正在分发则直接返回
if (mDispatchingValue) {
//标记分发失效
mDispatchInvalidated = true;
return;
}
//标记分发开始
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
//生命周期改变调用的方法 initiator 不为 null
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
//postValue/setValue 方法调用 传递的 initiator 为 null
for (Iterator<Map.Entry<Observer, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
//标记分发结束
mDispatchingValue = false;
}

considerNotify(ObserverWrapper)  方法:

private void considerNotify(ObserverWrapper observer) {
//检查状态 确保不会分发给 inactive 的 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;
}
//setValue 会增加 version ,初始 version 为-1
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
//noinspection unchecked
observer.mObserver.onChanged((T) mData);
}

可以看到 dispatchingValue 正是分发事件逻辑的处理方法,而 considerNotify 方法则确保了只将最新的数据分发给 active 状态下的 Observer 。

另外也可以看到 LiveData 引入了版本管理来管理数据 (mData)以确保发送的数据总是最新的。(具体不多讲)

dispatchingValue 这里分两种情况:

  1. ObserverWrapper 不为 null
  2. ObserverWrapper 为 null

需要着重讲一下。

2.4.1 ObserverWrapper 不为 null 的情况

上面提到过,LifecycleBoundObserver.onStateChanged 方法里调用了 activeStateChanged ,而该方法调用dispatchingValue(this);传入了 this ,也就是 LifecycleBoundObserver ,这时候不为 null 。

也就是说生命周期改变触发的流程就是这种情况,这种情况下,只会通知跟该 Owner 绑定的 Observer。

2.4.2 ObserverWrapper 为 null 的情况

上面我也提前说了,除了生命周期改变触发的流程外,还有 postValue&setValue 流程,来看下这俩方法。

private final Runnable mPostValueRunnable = new Runnable() {
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
//noinspection unchecked
//调用 setValue
setValue((T) newValue);
}
};

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

@MainThread
protected void setValue(T value) {
//必须在主线程调用 否则会 crash
assertMainThread(“setValue”);
mVersion++;//增加版本号
mData = value;
//传入了 null
dispatchingValue(null);
}

LiveData 的 postValue 方法其实就是把操作 post 到主线程,最后调用的还是 setValue 方法,注意 setValue 必须是在主线程调用。

并且可以看到** setValue 方法调用了 dispatchingValue 方法,并传入了 null ,这个时候的流程则会通知 active 的mObservers**。

到这里之前的剩下的所有疑问也都可以解答了。

LiveData 的两个流程都会走到 dispatchingValue 处理分发通知逻辑,并且在分发通知前会判断 owner 的状态,再加上 LiveData 本身内部的版本管理,确保了只会发送最新的数据给 active 状态下的 Observer

**注意:**LiveData 对同时多次修改数据做了处理,如果同时多次修改,只会修改为最新的数据。

3. 图解 LiveData

3.1 LiveData 类图

再看一遍类图,回顾一下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

(图2.LiveData 类图)

3.2 LiveData 流程图

Lifecycle 改变触发流程:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

(图3.Lifecycle 改变触发流程图)

Lifecycle postValue/setValue 触发流程:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

(图4.setValue 改变触发流程图)

4. LiveData tips and recipes

最后

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

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助

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

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

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

[外链图片转存中…(img-NEIWLJD6-1715796123661)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

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

  • 13
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值