LiveData执行流程
LiveData通过observe添加观察者,方法如下:
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
return;
}
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);
}
在以上代码中,observer被封装成了LifecycleBoundObserver对象,LifecycleBoundObserver是LiveData的内部类,继承ObserverWrapper并实现LifecycleEventObserver接口。ObserverWrapper中有成员变量mLastVersion,初始值START_VERSION为-1,用来表示observer的数据版本号。
owner.getLifecycle().addObserver(wrapper)对应的是LifecycleRegistry的addObserver方法,其中主要进行observer的保存和生命周期状态的同步,具体请参考Lifecycle组件部分。在addObserver方法中会执行statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState))方法,如下:
void dispatchEvent(LifecycleOwner owner, Event event) {
State newState = getStateAfter(event);
mState = min(mState, newState);
mLifecycleObserver.onStateChanged(owner, event);
mState = newState;
}
@Override
public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
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方法如下:
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;
}
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}
LiveData提供了postValue和setValue用来改变LiveData的数据。
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) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
粘性事件
在第一个Activity中调用postValue或setValue改变LiveData的值后,跳转到第二个Activity,并在第二个Activity中为LiveData设置观察者,此时第二个Activity中设置的观察者会接收到在第一个Activity中设置的LiveData值,即LiveData向观察者发送的数据默认为粘性的。原因在于新建的观察者数据版本号observer.mLastVersion为-1,在considerNotify中会执行observer.mObserver.onChanged回调。
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}
可以通过hook方式在调用LiveData.observe方法时改变observer.mLastVersion,使其等于LiveData.mVersion的值,这样在添加观察者时不会执行observer.mObserver.onChanged回调,使LiveData发送的数据变为非粘性。
新建一个类继承MutableLiveData并重写其observe方法
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
super.observe(owner, observer);
Class<LiveData> liveDataClass = LiveData.class;
try {
Field mObservers = liveDataClass.getDeclaredField("mObservers");
mObservers.setAccessible(true);
Object observers = mObservers.get(this);
Class<?> observersClass = observers.getClass();
Method methodGet = observersClass.getDeclaredMethod("get", Object.class);
methodGet.setAccessible(true);
Object objectWrapperEntry = methodGet.invoke(observers, observer);
Object objectWrapper = null;
if (objectWrapperEntry instanceof Map.Entry) {
objectWrapper = ((Map.Entry) objectWrapperEntry).getValue();
}
if (objectWrapper == null) {
throw new NullPointerException("ObserverWrapper can not be null");
}
Class<?> wrapperClass = objectWrapper.getClass().getSuperclass();
Field mLastVersion = wrapperClass.getDeclaredField("mLastVersion");
mLastVersion.setAccessible(true);
Field mVersion = liveDataClass.getDeclaredField("mVersion");
mVersion.setAccessible(true);
Object mV = mVersion.get(this);
mLastVersion.set(objectWrapper, mV);
mObservers.setAccessible(false);
methodGet.setAccessible(false);
mLastVersion.setAccessible(false);
mVersion.setAccessible(false);
} catch (Exception e) {
e.printStackTrace();
}
}