遵循 通过唯一可信源分发状态 的标准化开发理念。唯一可信源是指 生命周期独立于 视图控制器的 数据组件,通常是 单例 或共享 ViewModel。
EventBus 只是纯粹的 Bus,它 缺乏上述提到的 标准化开发理念 的约束,造成 诸如 毫无防备地收到 预期外的 不明来源的推送、拿到过时的数据 及 事件源追溯复杂度 为 n² 的局面。
EventBus 本身缺乏 Lifecycle 的加持,存在生命周期管理的一致性问题。这是 EventBus 的硬伤,也是我拒绝使用 EventBus 的最主要因素。
LiveData 是在 Google 希望确立 标准化、规范化 的开发模式,Google 十分克制地将其设计为,仅支持 状态
的输入和监听,从而,它不得不 在单例的配合下,承上启下地完成 状态 从 唯一可信源 到 视图控制器 的输送。
LiveData 有个坑需要注意,在视图控制器发生重建后,能够 自动倒灌 所观察的 LiveData 的最后一次数据,LiveData 被设计为粘性事件。
关于非粘性 LiveData 的实现,网上存在通过 “事件包装类”(只适合 kotlin 的情况) 和 “反射干预 LastVersion” (适用于 Java 的情况)两种方式来解决:
无论是使用哪一种实现,我都建议 遵循传统 LiveData 所遵循的开发理念,通过唯一可信源分发状态,来方便事件源头的追溯。
SingleLiveEvent.java
的问题在于它仅限于一个观察者。如果您无意中添加了多个,则只会调用一个,并且不能保证哪一个。(推荐: 使用事件包装器,在这种方法中,您可以明确地管理事件是否已经被处理,从而减少错误。他们现在只是一个消耗或者不消耗的消息。)
总之:把事件设计成你的状态的一部分。使用您自己的 事件 包装器并根据您的需求进行定制。
LiveData
是如何通信的?
就一句话,UI层注册好一个 observer,就存储到一个存储着观察者的 map 中,直到开发者调用 postValue/setValue 则遍历该 map,触发 observer 的onChanged 通知,在此过程中,都会监听组件的生命周期,并以此来判断所匹配的组件是否处于活动状态,否则直接 return。
PostValue
可以在任意线程中调用,而SetValue
只能在主线程中,因为PostValue
多了一步切换主线程的操作。
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
setValue((T) newValue);
}
};
@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;
}
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 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;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
// 敲黑板,划重点
observer.mObserver.onChanged((T) mData);
}
LiveData
的粘性事件
发送消息
早于注册事件
,注册的 VC 依然能够接收到消息,我们称之为粘性事件。即先调用LiveData
的postValue/setValue
方法,后注册observe
,依然能够收到onChange()
的通知。
为什么 LiveData
先发送后注册,也能够收到通知呢?是哪里分发了onChange()
?
原因在于当
LifecycleOwner
改变状态时,观察者会被通知。例如,如果LifecycleOwner
处于State#STARTED
状态,给定的观察者将收到Event#ON_CREATE、Event#ON_START
事件。
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
......
// 核心在这里
owner.getLifecycle().addObserver(wrapper);
}
// 跟踪到它的实现类里面
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);
}
// dispatchEvent表示将ON_CREATE、ON_START等事件分发给观察者,以达到监听生命周期的作用
......
}
}
void dispatchEvent(LifecycleOwner owner, Event event) {
State newState = getStateAfter(event);
mState = min(mState, newState);
✅ 切入点
mLifecycleObserver.onStateChanged(owner, event);
mState = newState;
}
// 看到mLifecycleObserver.onStateChanged(owner, event)是不是有种熟悉的感觉
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());
}
......
}
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);
}
}
// setValue()中也调用了一句dispatchingValue(null),只不过setValue传入的是null,而现在这里传入了一个this值
void dispatchingValue(@Nullable ObserverWrapper initiator) {
......
do {
mDispatchInvalidated = false;
if (initiator != null) {
✅切入点1
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;
}
private void considerNotify(ObserverWrapper observer) {
......
observer.mObserver.onChanged((T) mData);
}
所以 LiveData
的粘性事件,在于 LiveData
只要在注册观察者时,就会触发 LifecycleOwner
的状态改变,并且会将 ON_CREATE, ON_START, ON_RESUME
三种状态分发给观察者,而这就触发了 onChange
的通知。
网友评论