一 什么是LiveData
LiveData是一個(gè)可觀察數(shù)據(jù)變化的類,但是與其他觀察類不同的是,LiveData是可以感知到所持有類的生命周期的。所以我們一般用它來和Activity、Fragment或者service一起使用。這里有個(gè)很有好處的地方就是,LiveData的onChange方法,只會(huì)在activity在前臺(tái)的時(shí)候產(chǎn)生回調(diào),后面我們可以用例子來說明。
二 LiveData的好處
那么使用LiveData有什么好處呢?從LiveData的相關(guān)特性,我們可以歸納出以下幾點(diǎn):
1 確保UI和數(shù)據(jù)狀態(tài)保持一致
LiveData遵循觀察者模式,當(dāng)生命周期發(fā)生改變的時(shí)候,LiveData會(huì)通知觀察者對(duì)象。因此我們可以通過統(tǒng)一在觀察者對(duì)象數(shù)據(jù)中更新UI,而不是通過app數(shù)據(jù)的變更去改變UI。在我們這些對(duì)象發(fā)生變更的時(shí)候,我們的UI也會(huì)跟著改變。
2 不會(huì)有內(nèi)存泄漏
所有的觀察者都是綁定到owner的生命周期內(nèi)的,也就是說,如果owner被finish的時(shí)候,所有的觀察者也會(huì)被自動(dòng)銷毀。炒雞智能方便有木有?
3 不會(huì)因?yàn)锳ctivity被銷毀而導(dǎo)致崩潰
這種情況多數(shù)發(fā)生在我們的異步回調(diào)函數(shù)中,比如有時(shí)候我們回去通過異步線程來獲取網(wǎng)絡(luò)數(shù)據(jù)后,刷新我們的界面。這個(gè)時(shí)候,當(dāng)我們的activity被銷毀的時(shí)候,我們的異步線程回調(diào)才剛回來,這就導(dǎo)致了我們?cè)谝粋€(gè)廢棄的activity中更新他的UI,這就會(huì)導(dǎo)致異常崩潰的發(fā)生。
4 不再需要手動(dòng)去控制生命周期
UI組件只會(huì)在對(duì)象不是stop或者resume的時(shí)候進(jìn)行觀察,LiveData會(huì)自動(dòng)管理這一切。在正確的時(shí)候,給與觀察者以回調(diào)。
5 永遠(yuǎn)保持最新的數(shù)據(jù)狀態(tài)
當(dāng)觀察的對(duì)象不是處于激活狀態(tài)的時(shí)候,LiveData并不會(huì)去刷新數(shù)據(jù),而當(dāng)觀察的對(duì)象重新激活的時(shí)候,那么LiveData將會(huì)刷新最新的數(shù)據(jù)。最典型的是,如果你的Activity是后臺(tái)的時(shí)候,再次期間所有的數(shù)據(jù)變更,liveData都會(huì)選擇性的忽略,等到你重新喚醒Activity的時(shí)候,LiveData馬上就會(huì)刷新他的值,讓他和最后一個(gè)setValue(value)保持一致。
三 開始源碼之旅
接下來,我們從一段簡(jiǎn)單的源碼開始
viewModel.loadFiveUsers().observe(MainActivity.this, new Observer<List<User>>() {
@Override
public void onChanged(@Nullable List<User> users) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < users.size(); i++) {
User user = users.get(i);
sb.append("====================\n");
sb.append("uid:" + user.getUid() + "\n " + user.getUserName() + "\n" + user.getLastName() + "\n");
sb.append("\n");
}
tv_values.setText(sb.toString());
}
});
我們這里暫且忽略viewModel部門,我們只需要知道,viewModel.loadFiveUsers()返回的是一個(gè)LiveData<T>類型的數(shù)據(jù)就可以了。簡(jiǎn)單的說一下這段代碼,就是實(shí)時(shí)獲取當(dāng)前數(shù)據(jù)庫中的前5條數(shù)據(jù),并且把這5條數(shù)據(jù)通過TextView顯示出來。業(yè)務(wù)場(chǎng)景其實(shí)非常的簡(jiǎn)單。好了,接下來開始拆輪子
第一步:LiveData.observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer)Owner和observe是如何建立聯(lián)系的
我們進(jìn)入源碼的世界
@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);
}
首先,LiveData強(qiáng)調(diào)的是,observe方法必須是在UI線程中進(jìn)行調(diào)用的。我們從源碼可知
1 如果當(dāng)前的owner是Destroyed狀態(tài)的,那么我們就直接忽略掉了,這個(gè)是顯而易見的。
2 LiveData會(huì)先將當(dāng)前的owner和observe結(jié)合在一起,生成一個(gè)wrapper對(duì)象,然后嘗試observe和wrapper當(dāng)成key和value 添加進(jìn)mObservers中,這個(gè)mObservers其實(shí)就是一個(gè)map對(duì)象。如果發(fā)現(xiàn)這個(gè)key對(duì)應(yīng)的value已經(jīng)有值了,并且這value并不是我們即將put進(jìn)去的value,那么就會(huì)拋錯(cuò)
3 加入不存在的話,那么wrapper將會(huì)被添加進(jìn)當(dāng)前owner的生命周期中,進(jìn)行監(jiān)聽。
第二步:setValue(T value)
LiveData提供了兩個(gè)setValue的方法,一個(gè)是同步情況的調(diào)用
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
另一個(gè)是異步情況的調(diào)用
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
其實(shí)最后都是調(diào)用了 setValue((T) newValue);方法。我們來研究下這個(gè)方法,可以看到,他會(huì)先判斷當(dāng)前是否在主線程調(diào)用,如果不是的話,那么就會(huì)拋出錯(cuò)誤。然后就會(huì)把當(dāng)前LiveData的版本號(hào)mVersion++,把mData設(shè)置成最新的value。其實(shí)整個(gè)過程最麻煩的是dispatchingValue(null)這個(gè)方法。我們進(jìn)入這個(gè)方法進(jìn)行查看
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;
}
其實(shí)我們可以看到,這個(gè)個(gè)方法就是現(xiàn)在已有的觀察者進(jìn)行循環(huán),檢查到如果是當(dāng)前的觀察者,那么就調(diào)用considerNotify(iterator.next().getValue())方法。也即是找到最新的mData,進(jìn)行onchanged(mData)回調(diào)給觀察者。
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);
}
其實(shí)這個(gè)方法,會(huì)調(diào)用到
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
這個(gè)方法就是會(huì)去判斷當(dāng)前的owner的狀態(tài)是否是active狀態(tài),進(jìn)行是否分發(fā)的動(dòng)作。
四 生命周期中LiveData的回調(diào)情況
1 關(guān)于:永遠(yuǎn)保持最新的數(shù)據(jù)狀態(tài)
我們主動(dòng)setValue(T value)方法后,liveData調(diào)用的onChanged(T value)流程已經(jīng)分析完畢了,那么前面我們所說的,當(dāng)觀察的對(duì)象不是處于激活狀態(tài)的時(shí)候,LiveData并不會(huì)去刷新數(shù)據(jù),而當(dāng)觀察的對(duì)象重新激活的時(shí)候,那么LiveData將會(huì)刷新最新的數(shù)據(jù)。最典型的是,如果你的Activity是后臺(tái)的時(shí)候,再次期間所有的數(shù)據(jù)變更,liveData都會(huì)選擇性的忽略,等到你重新喚醒Activity的時(shí)候,LiveData馬上就會(huì)刷新他的值,讓他和最后一個(gè)setValue(value)保持一致。這個(gè)是怎么實(shí)現(xiàn)的呢?

其實(shí)就是如上圖所說的,我們的activity在后臺(tái)或者重新回到前臺(tái)的時(shí)候,都會(huì)回調(diào)到上面的onStateChanged()方法。當(dāng)Activity是后臺(tái)的時(shí)候,shouldBeActive返回的是false,那么
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);
}
}
中的dispatchingValue(this)就不會(huì)進(jìn)行分發(fā),從而不會(huì)觸發(fā)observe的onchanged(T mData) 方法。
2 Activity finish的時(shí)候,移除監(jiān)聽
上面的圖中我們可以看到,LiveData還會(huì)去判斷當(dāng)前的owner是否已經(jīng)被銷毀了,如果被銷毀了,還會(huì)調(diào)用removeObserver(mObserver);方法,這也就是我們不需要去關(guān)心內(nèi)存泄漏,或者在Activity finish情況下,還去嘗試更新UI的問題。
自此,LiveData的完整分析已經(jīng)完成。