LiveData是一個可以在給定生命周期內(nèi)觀察到的數(shù)據(jù)持有者類。一個觀察者可以與一個LifecycleOwner成對地添加,并且只有當(dāng)配對的LifecycleOwner處于活動狀態(tài)時邮利,這個觀察者才會收到數(shù)據(jù)變動的通知。
LiveData-ViewModel-Repository
以下是LiveData結(jié)合ViewModel請求數(shù)據(jù)的偽代碼垃帅,這也是JetPack中最常見的一種寫法延届。
ViewModel層:繼承ViewModel并創(chuàng)建LiveData,通過postValue將數(shù)據(jù)發(fā)射給UI贸诚。
class ExViewModel() : ViewModel() {
private lateinit var repo: ExRepo
val liveData: MutableLiveData<String> = MutableLiveData()
//調(diào)用postValue通知UI數(shù)據(jù)被改變
fun loadData() = liveData.postValue(repo.loadDataFromRepo())
}
Repository層:從網(wǎng)絡(luò)或者數(shù)據(jù)庫中請求數(shù)據(jù)方庭。
class ExRepo() {
//網(wǎng)絡(luò)請求或者從數(shù)據(jù)庫中請求
fun loadDataFromRepo(): String = "網(wǎng)絡(luò)請求返回的數(shù)據(jù)"
}
UI層:注冊LiveData的觀察者,接收數(shù)據(jù)變化的通知來更新UI
class ExFragment: Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val viewModel = ViewModelProviders.of(this).get(ExViewModel::class.java)
//注冊觀察者
viewModel.liveData.observe(this, object:Observer<String> {
override fun onChanged(value: String) {
//請求數(shù)據(jù)成功后酱固,通知UI刷新界面
updateUI()
}
})
//請求數(shù)據(jù)
viewModel.loadData()
}
}
上面三層基本上就是一個網(wǎng)絡(luò)請求的閉環(huán)械念,Repository負(fù)責(zé)從網(wǎng)絡(luò)或者數(shù)據(jù)庫中請求數(shù)據(jù),ViewModel負(fù)責(zé)調(diào)用Repository的數(shù)據(jù)运悲,并利用LiveData的postValue()/setValue()方法將數(shù)據(jù)的更新通知到UI層龄减,UI則只需要注冊一個LiveData的觀察者,當(dāng)所匹配的LiveData調(diào)用postValue()/setValue()時班眯,就會收到onChange()的通知希停,去做更新UI的操作。
(此圖來源網(wǎng)上)
LiveData遵循觀察者模式署隘,它的厲害之處不僅在于數(shù)據(jù)有變化時能及時通知UI宠能,而且LiveData能夠感知Activity、Fragment等組件的生命周期磁餐,隨組件銷毀而自動銷毀违崇,不用開發(fā)者去操心,極大的減少了內(nèi)存泄漏的可能诊霹。
那LiveData是如何通信并且感知組件的生命周期的呢羞延?
LiveData的通信原理
從上面例子可以知道LiveData的核心主要在于這兩步,liveData.observe()以及l(fā)iveData.postValue()畅哑,一個是注冊觀察者肴楷,一個是發(fā)送通知。那么下面的解析就將這兩個函數(shù)作為切入點(diǎn)荠呐。
1.LiveData.observe()
從liveData.observe()跟蹤進(jìn)去:
LiveData.java
private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
new SafeIterableMap<>();
......
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
//? 第一部分
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方法傳有兩個參數(shù)LifecycleOwner和Observer赛蔫,LifecycleOwner是一個具有Android生命周期的類,一般傳入的是Activity和Fragment泥张,Observer是一個接口呵恢,內(nèi)部存在void onChanged(T t)方法。
? 第一部分: observe內(nèi)部一開始就存在一個生命周期的判斷媚创,
if (owner.getLifecycle().getCurrentState() == DESTROYED) {return;}
當(dāng)組件生命周期已經(jīng)Destroy了渗钉,也就沒有必要再繼續(xù)走下去,則直接return。在這里鳄橘,LiveData對生命周期的感知也就慢慢顯現(xiàn)出來了声离。
? 第二部分: 首先以LifecycleOwner和Observer作為參數(shù)創(chuàng)建了一個LifecycleBoundObserver對象,接著以O(shè)bserver為key瘫怜,新創(chuàng)建的LifecycleBoundObserver為value术徊,存儲到mObservers這個map中。在后面LiveData postValue中會遍歷出該map的value值ObserverWrapper鲸湃,獲取組件生命周期的狀態(tài)赠涮,已此狀態(tài)來決定分不分發(fā)通知(這部分詳情見“第二小節(jié)postValue()”)
那LifecycleBoundObserver是什么?
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
.......
}
從源碼可以看到暗挑,LifecycleBoundObserver繼承ObserverWrapper并且實(shí)現(xiàn)了LifecycleEventObserver的接口笋除,LifecycleEventObserver是監(jiān)聽組件生命周期更改并將其分派給接收方的一個接口,而在LifecycleBoundObserver的構(gòu)造函數(shù)中將observer傳給了父類ObserverWrapper炸裆。LifecycleBoundObserver其實(shí)只是包裹著LifecycleOwner和Observer得一個類垃它,其中的實(shí)現(xiàn)有點(diǎn)代理模式的味道晒衩。
? 第三部分: owner.getLifecycle().addObserver(wrapper)
將新創(chuàng)建的LifecycleBoundObserver添加到Lifecycle中听系,也就是說這個時候觀察者注冊成功,當(dāng)LifecycleOwner也就是組件的狀態(tài)發(fā)生改變時,也會通知到所匹配的observer。
到這里损合,UI層viewModel.liveData.observe(this, object:Observer<String> { override fun onChanged(value: String) {} })
注冊觀察者的內(nèi)部解析也就大致清楚了。
2.postValue()
liveData.postValue()是作為一個發(fā)射方來通知數(shù)據(jù)改變,其內(nèi)部又做了哪些工作纠修?接下來就一探究竟吁系。直接從postValue中最核心的部分在于將參數(shù)value賦值給了一個全局變量源碼開始:
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
postValue中首先將參數(shù)value賦值給了一個全局變量mPendingData福荸,它的初始值為一個空對象背传,而mPendingData只是作為一個中間媒介來存儲value的值,在后續(xù)的操作中會用到,我們就暫時先記住它冤灾。
在最后就是一個將線程切換到主線程的操作移宅,主要看mPostValueRunnable的實(shí)現(xiàn):
private final Runnable mPostValueRunnable = new Runnable() {
@SuppressWarnings("unchecked")
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
setValue((T) newValue);
}
};
在Runnable中,mPendingData賦值給了臨時變量newValue,最后調(diào)用了setValue()方法。我們都知道LiveData發(fā)送通知可以使用PostValue或者SetValue攻晒,而他兩的區(qū)別就在于,PostValue可以在任意線程中調(diào)用,而SetValue只能在主線程中,因?yàn)镻ostValue多了一步上面切換主線程的操作。
OK,接下來就是PostValue/SetValue最核心的部分。
@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;
}
在setValue中贾虽,參數(shù)value將值賦給了一個全局變量mData,而這個mData最后將通過mObserver.onChanged((T) mData);將需要修改的value值分發(fā)給了UI蓬豁。最后調(diào)用傳入一個null調(diào)用dispatchingValue方法绰咽。
由于dispatchingValue里的參數(shù)為null,也就順理成章的走到了? 第二部分地粪。else一進(jìn)入就是迭代器在遍歷mObservers取募,而mObservers在第一小節(jié)“1.LiveData.observe()”中說得很清楚,它作為一個map蟆技,存儲了Observer和ObserverWrapper玩敏。通過遍歷斗忌,將每個觀察者所匹配的ObserverWrapper作為參數(shù)傳給了considerNotify()方法。
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);
}
而在considerNotify()中旺聚,先通過observer來獲取組件生命周期的狀態(tài)织阳,如果處于非活動狀態(tài),則拒絕發(fā)起通知砰粹。在該方法的最后唧躲, observer.mObserver.onChanged((T) mData)
,是不是很熟悉碱璃,這就是UI層一開始就實(shí)現(xiàn)的接口弄痹,而就在這找到了最后的發(fā)送方。
小結(jié)
LiveData是如何通信的嵌器?就一句話界酒,UI層注冊好一個observer,就存儲到一個存儲著觀察者的map中嘴秸,直到開發(fā)者調(diào)用postValue/setValue則遍歷該map,分發(fā)出observer的onChanged通知庇谆,在此過程中岳掐,都會監(jiān)聽組件的生命周期,并以此來判斷所匹配的組件是否處于活動狀態(tài)饭耳,否則直接return串述。
三、LiveData的粘性事件
發(fā)送消息事件早于注冊事件寞肖,依然能夠接收到消息的通知的為粘性事件
即先調(diào)用LiveData的postValue/setValue方法纲酗,后注冊observe,依然能夠收到onChange()的通知新蟆。從上面的分析可以知道觅赊,LiveData最后postValue是將通知分發(fā)給已經(jīng)注冊好的觀察者,而LiveData的粘性事件是先發(fā)送后注冊琼稻,那為什么也能夠收到通知呢吮螺?是哪里分發(fā)了onChange()?
我們知道粘性事件是注冊后就收到了通知,那么就可以以liveData.observe()為切入點(diǎn)帕翻,康康源碼中的實(shí)現(xiàn)鸠补。
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
......
owner.getLifecycle().addObserver(wrapper);
}
LiveData注冊觀察者,最核心在于owner.getLifecycle().addObserver(wrapper);
addObserver是用來添加一個LifecycleObserver嘀掸,當(dāng)LifecycleOwner改變狀態(tài)時紫岩,它會被通知。例如睬塌,如果LifecycleOwner處于State#STARTED狀態(tài)泉蝌,給定的觀察者將收到Event#ON_CREATE歇万、Event#ON_START事件。
而我們跟蹤到它的實(shí)現(xiàn)類里面梨与,
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);
? 切入點(diǎn)
statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
popParentState();
// mState / subling may have been changed recalculate
targetState = calculateTargetState(observer);
}
......
}
}
LifecycleRegistry繼承了Lifecycle堕花,是一個處理多個觀察者的類,在這個類中的addObserver方法有一個被我標(biāo)記?切入點(diǎn)
statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState))
粥鞋,dispatchEvent表示將ON_CREATE缘挽、ON_START等事件分發(fā)給觀察者,以達(dá)到監(jiān)聽生命周期的作用呻粹。在dispatchEvent方法中壕曼,LifecycleEventObserver通過onStateChanged接口分發(fā)給了相應(yīng)的觀察者,如下:
void dispatchEvent(LifecycleOwner owner, Event event) {
State newState = getStateAfter(event);
mState = min(mState, newState);
? 切入點(diǎn)
mLifecycleObserver.onStateChanged(owner, event);
mState = newState;
}
看到mLifecycleObserver.onStateChanged(owner, event)
是不是有種熟悉的感覺等浊,其實(shí)在第二節(jié)源碼分析中腮郊,類LifecycleBoundObserver就實(shí)現(xiàn)了LifecycleEventObserver接口,并重寫了onStateChanged方法筹燕。
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;
}
? 切入點(diǎn)
activeStateChanged(shouldBeActive());
}
......
}
如果當(dāng)前生命周期狀態(tài)處于DESTROYED轧飞,則將觀察者從列表中移除,防止內(nèi)存泄漏撒踪,接著就調(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();
}
? 切入點(diǎn)
if (mActive) {
dispatchingValue(this);
}
}
在 ? 切入點(diǎn)之前代碼不需要多看,只是一些判斷當(dāng)前活動是否活躍的一起邏輯制妄,核心在于dispatchingValue(this)
掸绞,看到這個方法,是不是又感覺到一絲熟悉耕捞,如果看了第二節(jié)的分析衔掸,就會發(fā)現(xiàn)第二節(jié)setValue()中也調(diào)用了一句dispatchingValue(null),只不過setValue傳入的是null,而現(xiàn)在這里傳入了一個this值俺抽。接下啦就來看看傳如參數(shù)和null有什么不同敞映?
void dispatchingValue(@Nullable ObserverWrapper initiator) {
......
do {
mDispatchInvalidated = false;
if (initiator != null) {
?切入點(diǎn)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;
}
因?yàn)閐ispatchingValue傳入的參數(shù)不為null,則邏輯就走進(jìn)了 ?切入點(diǎn)1中磷斧,接著將initiator作為參數(shù)驱显,調(diào)用了considerNotify方法,這個其實(shí)和setValue最后調(diào)用的方法是一致的瞳抓,只是傳入的參數(shù)不同罷了埃疫。considerNotify方法中最后將數(shù)據(jù)發(fā)送給了觀察者。
private void considerNotify(ObserverWrapper observer) {
......
observer.mObserver.onChanged((T) mData);
}
到此孩哑,整個流程也就梳理完成栓霜。
小結(jié)
LiveData的粘性事件,在于LiveData只要在注冊觀察者時横蜒,就會觸發(fā)LifecycleOwner的狀態(tài)改變胳蛮,并且會將ON_CREATE,ON_START,ON_RESUME三種狀態(tài)分發(fā)給觀察者销凑,而這,就觸發(fā)了onChange的通知仅炊。