LiveData是Google發(fā)布的一個(gè)架構(gòu)組件,它是一個(gè)數(shù)據(jù)持有類(lèi)金矛,并且數(shù)據(jù)可以被觀察毙玻。區(qū)別于普通的被觀察者,LiveData最大的特點(diǎn)是具備生命周期感知能力速和,即它僅更新處于活動(dòng)生命周期狀態(tài)的應(yīng)用程序組件觀察者(例如Activity/Fragment)意蛀。因此耸别,LiveData可以很好的解決內(nèi)存泄漏問(wèn)題,以及常見(jiàn)的view空指針異常县钥。
一秀姐、LiveData如何感知生命周期
在Android架構(gòu)組件之Lifecycle源碼解析一文中,我們了解到Lifecycle-Aware組件的核心就是生命周期感知若贮,要明白LiveData為什么能感知生命周期省有,就要以Lifecycle-Aware組件的原理為基礎(chǔ)。由于26.1.0及更高版本Support支持庫(kù)中的Activity和Fragment已經(jīng)實(shí)現(xiàn)了LifecycleOwner接口谴麦,因此Activity/Fragment就是LifecycleOwner蠢沿,而且它們內(nèi)部都會(huì)有一個(gè)LifecycleRegistry來(lái)存放生命周期State、Event等匾效。通過(guò)Lifecycle-Aware源碼分析舷蟀,我們可以知道在初始化Lifecycle組件時(shí)會(huì)為每個(gè)Activity/Fragment添加一個(gè)ReportFragment(無(wú)UI界面的Fragment),當(dāng)Activity執(zhí)行相應(yīng)生命周期方法的時(shí)候面哼,也會(huì)同步的執(zhí)行ReportFragment的生命周期方法野宜。因此,Lifecycle組件的核心就是通過(guò)無(wú)UI界面的Fragment來(lái)實(shí)現(xiàn)生命周期的監(jiān)聽(tīng)魔策,它會(huì)在執(zhí)行其生命周期方法的時(shí)候更新LifecycleRegistry里的生命周期State匈子、Event,,并且通過(guò)handleLifecycleEvent()方法來(lái)通知對(duì)應(yīng)的觀察者闯袒。
基于Lifecycle組件生命周期感知原理虎敦,那么只要讓LiveData注冊(cè)對(duì)Activity/Fragment的生命周期的監(jiān)聽(tīng),那么LiveData自然也就擁有了生命周期感知能力政敢。具體看一下LiveData的源碼實(shí)現(xiàn):
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
... ...
owner.getLifecycle().addObserver(wrapper);
}
由源碼可知其徙,如果當(dāng)前的LifecycleOwner處于DESTROYED狀態(tài),則忽略喷户。否則唾那,將傳入的觀察者做一個(gè)封裝,然后添加到Activity/Fragment的LifecycleRegistry中去摩骨,當(dāng)Activity/Fragment的什么周期發(fā)生變化時(shí)通贞,就會(huì)通知這個(gè)封裝的觀察者,即LiveData擁有了生命周期感知能力恼五。
二昌罩、LiveData注冊(cè)觀察者
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
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);
}
由源碼可知,observe()注冊(cè)觀察者方法運(yùn)行在主線程灾馒。同時(shí)茎用,observe()方法會(huì)將傳入的觀察者對(duì)象封裝成一個(gè)LifecycleBoundObserver對(duì)象,之后再將這個(gè)wrapper對(duì)象添加到Activity/Fragment的LifecycleRegistry中去。因此轨功,對(duì)于Activity/Fragment而言旭斥,這個(gè)wrapper對(duì)象是觀察者,Activity/Fragment生命周期的變化都會(huì)通知到wrapper古涧。
那么垂券,緊接著我們一起來(lái)看一下LifecycleBoundObserver的源碼,而且配合上LifecycleRegistry靜態(tài)內(nèi)部類(lèi)ObserverWithState的源碼看效果更佳:
// LifecycleRegistry # ObserverWithState
static class ObserverWithState {
State mState;
GenericLifecycleObserver mLifecycleObserver;
ObserverWithState(LifecycleObserver observer, State initialState) {
mLifecycleObserver = Lifecycling.getCallback(observer);
mState = initialState;
}
void dispatchEvent(LifecycleOwner owner, Event event) {
State newState = getStateAfter(event);
mState = min(mState, newState);
mLifecycleObserver.onStateChanged(owner, event);
mState = newState;
}
}
// LiveData # LifecycleBoundObserver
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<T> observer) {
super(observer);
mOwner = owner;
}
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
由源碼可知羡滑,當(dāng)Activity/Fragment生命周期發(fā)生變化時(shí)菇爪,最終會(huì)去回調(diào)觀察者的onStateChanged()方法。因此柒昏,我們先看一下LifecycleBoundObserver的onStateChanged()方法凳宙。很明顯,如果Activity/Fragment的當(dāng)前狀態(tài)是DESTROYED职祷,那么就將這個(gè)觀察者移除氏涩,也就意味著解除了與Activity/Fragment的關(guān)聯(lián),這就是LiveData可以避免內(nèi)存泄漏的原因有梆。接著是尖,會(huì)調(diào)用activeStateChanged()方法。
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);
}
}
可以看到淳梦,當(dāng)LifecycleOwner的狀態(tài)處于STARTED或RESUMED時(shí)析砸,傳入newActive的值為true昔字,即LifecycleBoundObserver會(huì)被標(biāo)記為激活狀態(tài)爆袍,生命周期變化將會(huì)通知處于激活狀態(tài)的觀察者。
三作郭、LiveData通知觀察者
在上面的分析中陨囊,我們可以知道當(dāng)Activity/Fragment生命周期變化時(shí),如果Activity/Fragment處于活動(dòng)狀態(tài)夹攒,則會(huì)將生命周期變化通知觀察者蜘醋。
其次,我們也可以通過(guò)改變LiveData里面的數(shù)據(jù)內(nèi)容咏尝,然后再將數(shù)據(jù)的變化通知觀察者压语。具體主要體現(xiàn)在setValue()和postValue()這兩個(gè)方法上。
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
由源碼可知编检,setValue()方法只能運(yùn)行在主線程上胎食,而postValue()方法可以運(yùn)行在任意線程上,但是Observer的OnChange回調(diào)最終會(huì)執(zhí)行在主線程上允懂。
我們注意到厕怜,不管是哪種通知觀察者的方式,都會(huì)調(diào)用到dispatchingValue()這個(gè)方法,下面就具體來(lái)看一下:
private 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<T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
由源碼可知粥航,mDispatchingValue和mDispatchInvalidated只在dispatchingValue方法中使用琅捏,顯然這兩個(gè)變量是為了防止重復(fù)分發(fā)相同的內(nèi)容。接下來(lái)递雀,我們注意到柄延,無(wú)論傳入的initiator是否為空,都會(huì)走到considerNotify()這個(gè)方法:
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;
//noinspection unchecked
observer.mObserver.onChanged((T) mData);
}
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
由源碼可知缀程,如果Activity/Fragment處于非活動(dòng)狀態(tài)拦焚,則忽略。也就是說(shuō)杠输,如果當(dāng)前界面是不可見(jiàn)的赎败,那么就不會(huì)去通知觀察者,因此可以解決常見(jiàn)的view空指針異常問(wèn)題蠢甲。如果當(dāng)前界面處于活動(dòng)狀態(tài)僵刮,則會(huì)去回調(diào)注冊(cè)進(jìn)來(lái)的觀察者的onChanged()方法,之后進(jìn)行相應(yīng)的邏輯操作鹦牛。