LiveData的官方定义:LiveData是一种可以在给定生命周期内被观察的数据承载类。
1. 添加观察者的方式
有两种方式添加观察者:
- 通过observe(Observer)方法添加的观察者只有在生命周期拥有者活跃(处于STARTED或RESUMED状态)的时候才会接收到LiveData的修改通知,在生命周期拥有者进入DESTORUYED状态时会自动移除所有观察者。
- 通过observeForever(Observer)方法添加的观察者会一直接收到LiveData的修改通知,必须在适当时机调用removeObserver(Observer)。
1.1. observe(Observer)方式
observe(Observer)添加观察者的源码为:
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
//1.必须在主线程添加
assertMainThread("observe");
//2.在DESTROYED状态不允许添加
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
return;
}
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
//3. 不允许将相同的观察者添加给不同的生命周期拥有者
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
//4. 不重复添加生命周期观察者
if (existing != null) {
return;
}
owner.getLifecycle().addObserver(wrapper);
}
该方式先将生命周期拥有者对象和观察者对象封装成一个LifecycleBoundObserver对象,该对象继承ObserverWrapper并实现LifecycleEventObserver,因此该对象即是LiveData观察者又是生命周期事件观察者,分别将该对象加入到LiveData观察者列表mObservers中和生命周期观察者列表中。通过JetPack之Lifecycle观察者的实现方式解读可以知道:当生命周期发生变化时生命周期事件观察者的onStateChanged()方法会被回调。下面看一下该方法:
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mOwner;
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
//当接收到DESTROYED事件时会移除LiveData观察者
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
}
当有生命周期变化事件通知时,activeStateChanged(shouldBeActive())方法将会被调用,shouldBeActive()决定了是否通知LiveData观察者,注意shouldBeActive()方法中判断生命周期拥有者处于激活状态是当前状态大于等于STARTED枚举类型,这里RESUMED枚举类型是第一大,STARTED枚举类型是第二大。shouldBeActive()方法定义在虚类ObserverWrapper中:
private abstract class ObserverWrapper {
final Observer<? super T> mObserver;
boolean mActive; //表示该Observer是否处于激活状态
int mLastVersion = START_VERSION;
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);
}
}
}
newActive是指当前生命周期拥有者的激活状态,LiveData观察者得到通知必须有两个条件:1.新状态与原状态不相同;2.必须处于激活状态。因此我们可以得到一下结论:
1.在Activity/Fragment中首次添加LiveData观察者,LiveData的初始值是会通知给观察者的;
2.在Activity/Fragment从后台切到前台时,会走onResume()回调,newActive、mActive均为true(只要大雨onStart的状态均为true)但是LiveData观察者不会接到通知。
3.当调用setValue()函数时,处于pause状态的LifeCyclerOwner会收到通知,这是因为当Fragment处于OnPause状态时会触发LifecycleRegistry更新其mState状态:
//LifecycleRegistry.java
//生命周期拥有者生命周期变化时会调用该函数
public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
State next = getStateAfter(event); //对于PAUSE事件,则next = STARTED
moveToState(next);
}
//LifecycleRegistry.java
static State getStateAfter(Event event) {
switch (event) {
case ON_CREATE:
case ON_STOP:
return CREATED;
case ON_START:
case ON_PAUSE: //对于PAUSE事件,下一个状态被置为STARTED(State类型枚举)
return STARTED;
case ON_RESUME:
return RESUMED;
case ON_DESTROY:
return DESTROYED;
case ON_ANY:
break;
}
throw new IllegalArgumentException("Unexpected event value " + event);
}
//LifecycleRegistry.java
private void moveToState(State next) {
if (mState == next) {
return;
}
//对于PAUSE事件,将mState置为STARTED
mState = next;
if (mHandlingEvent || mAddingObserverCounter != 0) {
mNewEventOccurred = true;
// we will figure out what to do on upper level.
return;
}
mHandlingEvent = true;
sync();
mHandlingEvent = false;
}
//class LifecycleBoundObserver
boolean shouldBeActive() {
//对于处于PAUSE状态的生命周期拥有者,mState = STARTED,这里返回true
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
1.2 observeForever(Observer)方法
observeForever(Observer)添加观察者的源码为:
public void observeForever(@NonNull Observer<? super T> observer) {
//1.必须在主线程添加
assertMainThread("observeForever");
AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
//2.不能将同一个Observer对象同时使用observe()方式添加和observeForever()方式添加
if (existing instanceof LiveData.LifecycleBoundObserver) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
//3.参数true表示通知观察者
wrapper.activeStateChanged(true);
}
该方式将观察者封装成一个AlwaysActiveObserver对象,并添加到观察者列表mObservers中去,并且该方式在添加一个观察者对象时会立即通知该观察者对象。
2. 观察者的通知方式
通过上一节的论述我们知道:不管是通过observe()方式还是observeForver()方式添加的观察者,首次添加时其对应LiveData观察者都会收到通知;不同的是:当LiveData发生变化时,前者的观察者必须在生命周期拥有者处于激活状态时才会收到通知,若生命周期处于非激活状态时LiveData发生变化,那么当生命周期拥有者重新恢复激活状态时会通知观察者,而后者不论生命周期拥有者处于激活与否LiveData观察者都会得到通知。观察者也分为两种:AlwayseActiveObserver和LifecycleBoundObserver。观察者的通知方式分为两种:
- 全局通知;
- 部分通知。
看一下具体的代码:
//LiveData.java
void dispatchingValue(@Nullable ObserverWrapper initiator) {
//mDispatchingValue表示正在分发通知,mDispatchInvalidated表示是否无效分发。
//当正在分发时又触发了一次分发操作,即会禁用当前分发,并通知前一次未完成的分发是无效的,前一次分发即会停止分发并重新分发所有通知。
//所有操作都在主线程,这里的重入不会是多线程导致的,而是嵌套导致的
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(); ) {
//该处是嵌套发生的地方,dispatchingValue()方法由setValue()方法引发调用,
//若在此处通知LiveData观察者,并在观察者的回调中继续调用setValue()方法机会产生嵌套。
//调用链为:dispatchingValue -> observer.onChanged -> setValue -> dispatchingValue
considerNotify(iterator.next().getValue());
//mDispatchInvalidated = true时跳出for循环,但是又会重新进入while循环
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
当initiator不为null时,前者只通知initiator这一个观察者,通知的场景是调用setValue()方法;若initiator为null时则通知mObservers中的所有观察者,通知的场景是调用observeForever()方法添加一个观察者或调用removeObserver移除一个观察者等。真正通知观察者的操作是在considerNotify()方法中进行的:
private void considerNotify(ObserverWrapper observer) {
//如果observer的实际类型是LifecycleBoundObserver时,会在生命周期拥有者变为非激活状态时
//通知该observer,并将其mActive设置为false,因此在这里就跳过该类observer
if (!observer.mActive) {
return;
}
//如果observer的实际类型是AlwayseActiveObserver时,其shouldBeActive()返回值恒为true,因此对于该类observer的mActive不会被设置为false
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
//如果observer的版本号已经被更新为LiveData的最新版本号,不会通知观察者
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}
通过setValue()时会触发更新所有观察者,在遍历过程中类型为LifecycleBoundObserver且其mActive为false的观察者得不到通知,类型为AlwayseActiveObserver的观察者将会一直收到通知。