LiveData 是一个可感知宿主生命周期变化的组件,在宿主活跃状态下 在宿主执行销毁(DESTROYED)时,自动解除回调,
1.LiveData是怎样实现感知宿主知生命周期的?又是如何自动解除回调的?
2.数据更新后是如何通知观察者的?
3.在宿主处在不活跃状态时做数据更新,待宿主重新处于活跃状态再通知观察者,是怎么实现的?
javascript
LivewData<String> data = new MutableLiveData<String>();
data.observe(LifecycleOwner,new Observer<String>(){
void onChanged(String value){
// update ui
};
});
data.setValue("1111");
data.postValue("2222");
下文列举的源码基于 LivewData-core:2.3.1 版本
observe
less
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
//执行的线程 非主线程 抛出异常
assertMainThread("observe");
//如果宿主是DESTROYED销毁状态,无需操作
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
//将LifecycleOwner宿主和observer观察者 包装成一个LifecycleBoundObserver对象
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
//将LifecycleBoundObserver对象放到mObservers链表中
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
//返回的existing 不为空,说明当前observer之前已经添加过了
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
//使用LifecycleOwner宿主获取LifecycleRegistry,
//并将LifecycleBoundObserver这个观察者注册到LifecycleRegistry中
owner.getLifecycle().addObserver(wrapper);
}
看看LifecycleBoundObserver包装类的代码
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
.....
}
LifecycleBoundObserver的父类
private abstract class ObserverWrapper {
final Observer<? super T> mObserver;
boolean mActive;
int mLastVersion = START_VERSION;
ObserverWrapper(Observer<? super T> observer) {
mObserver = observer;
}
.....
}
kotlin
到这里,如果知道Lifecycle的实现原理,那么已经可以看出LiveData是怎么感知宿主生命周期的了
分析一下observe方法 做了些啥...
1.线程检查,非主线程不能调用observe
2.检查宿主状态,要是宿主是已经执行onDestory了,那么可以直接return了
3.将LifecycleOwner宿主和observer观察者 包装成一个LifecycleBoundObserver对象
4.将LifecycleBoundObserver对象放到mObservers链表中
5.LifecycleBoundObserver是实现了LifecycleEventObserver接口,那么LifecycleBoundObserver就相当于我们使用
Lifecycle时候的 LifecycleObserver生命周期观察者
6.将LifecycleBoundObserver这个生命周期观察者注册到LifecycleRegistry中,让它接收LifecycleRegistry派发的生命周期变化事件
既然 LiveData 把内部类 LifecycleBoundObserver作为 生命周期的观察者,那么我们就看看它的onStateChanged里是怎样处理生命周期事件
java
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mOwner;
.....
//判断宿主是否处于活跃状态
//最新生命周期状态值是否 >= STARTED,即宿主状态是否为STARTED或者RESUMED
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
//获取宿主的生命周期状态值,如处于DESTROYED,那就解除当前观察者
Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
if (currentState == DESTROYED) {
removeObserver(mObserver);
return;
}
Lifecycle.State prevState = null;
while (prevState != currentState) {
prevState = currentState;
//先判断宿主是否活跃状态,传到activeStateChanged中
activeStateChanged(shouldBeActive());
currentState = mOwner.getLifecycle().getCurrentState();
}
}
.......
}
private abstract class ObserverWrapper {
final Observer<? super T> mObserver;
//记录上一次收到宿主生命周期变化时,宿主是否活跃状态
boolean mActive;
//观察者内部上一次更新数据的版本号
int mLastVersion = START_VERSION;
ObserverWrapper(Observer<? super T> observer) {
mObserver = observer;
}
void activeStateChanged(boolean newActive) {
//当前的状态与上一次状态比较,
//如果两者一样,则直接return
if (newActive == mActive) {
return;
}
//记录是否活跃状态
mActive = newActive;
changeActiveCounter(mActive ? 1 : -1);
//如果当前是活跃状态
if (mActive) {
//进行数据调度处理
dispatchingValue(this);
}
}
}
scss
onStateChanged()分析
1.收到宿主生命周期变化后,判断宿主是否DESTROYED,是则解除当前观察者,
那么到这里已经解答了第一个问题.
2.shouldBeActive()方法是判断宿主当前是否活跃,生命周期状态值是否 >= STARTED视为活跃状态.
(即宿主生命周期状态是否为STARTED或者RESUMED)
3.activeStateChanged()中先比较事件前后,活跃状态是否变化
3.1.如两者相等,说明 活跃状态没有变化,无需执行余下操作
3.2.如两者不相等,则更新mActive值
3.3.如mActive为true,代表当前宿主是活跃状态,而上一次是非活跃状态,并使用dispatchingValue()进行数据处理
3.4.那么到这里也就解答了第三个问题,原理就是收到宿主生命周期事件时对比先后的活跃状态,如前后不相等,并且
当前是活跃,则会进行数据处理(通知LiveData的观察者)
接下来看dispatchingValue()
ini
void dispatchingValue(@Nullable ObserverWrapper initiator) {
//判断当前是否正在执行调度
if (mDispatchingValue) {
//标记 设置正在执行的循环调用无效
mDispatchInvalidated = true;
return;
}
//标记当前正在执行调度
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
//如initiator不为空,只通知指定的initiator观察者
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
// 获取mObservers迭代器,通知所有LiveData的观察者
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
//具体执行某个观察者
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
private void considerNotify(ObserverWrapper observer) {
//如当前宿主不活跃,不执行通知
if (!observer.mActive) {
return;
}
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
//比较 LiveData观察者记录的数据版本号 和 LiveData自身记录的数据版本号
if (observer.mLastVersion >= mVersion) {
return;
}
//更新观察者的数据版本号
observer.mLastVersion = mVersion;
//通知数据更新
observer.mObserver.onChanged((T) mData);
}
dispatchingValue()分析
arduino
1.mDispatchingValue标记当前是否正在执行事件派发
2.mDispatchInvalidated标记正在执行的 do-while 循环调用是否有效
3.do-while 正常情况只执行一遍,但如果正在for循环中,dispatchingValue()被再次调用
,那么结合两个标记位,正在执行的for就会退出,并再一次执行do{}
4.比较两个数据版本号,如观察者记录数据版本号落后于LiveData自身的数据版本号,则通知观察者数据更新
postValue:子线程使用
java
protected void postValue(T value) {
boolean postTask;
//加锁
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(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);
}
};
postValue分析
1.postTask的值代表是否有未处理的数据,并将需更新的数据赋值给mPendingData
2.如果postTask为true,则通过Handleg通知主线程执行mPostValueRunnable,
如果postTask为false,说明上一个数据的mPostValueRunnable还没执行,那么就只需要直接将最新数据赋值给mPendingData
即可,待主线程Handle处理上一个数据的mPostValueRunnable,mPendingData自然是最新的,这也是LiveData的特性,
只保持最新的状态数据
3.mPostValueRunnable中将mPendingData在赋值给一个新的对象,并重新将mPendingData置为NOT_SET,
并待用setValue
setValue
typescript
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
1.LiveData的数据版本号mVersion递增1,用于在dispatchingValue的流程中与LifecycleBoundObserver中的数据版本号对比。
以上就是LiveData的实现逻辑分析。 至于数据倒灌出现的原因:
1.主要是LiveData是基于Lifecycle的,而Lifecycle中每添加一个新的LifecycleObserver,就会从INITIALIZED状态至宿主最新的生命周期状态 的这个范围内所有涉及到的生命周期都会回调给LifecycleObserver,那对与LiveData而言就是回调到LifecycleBoundObserver.onStateChanged中
2.LiveData 和 LifecycleBoundObserver 各自版本号不相等,结合第1点,就最终导致数据倒灌。