LiveData是什么?
1.首先LiveData在用法上其實(shí)是與數(shù)據(jù)實(shí)體類是一樣的東西,它負(fù)責(zé)暫存數(shù)據(jù)。
2.其次LiveData其實(shí)也是一個觀察者模式的數(shù)據(jù)實(shí)體類,它可以跟它注冊的觀察者回調(diào)數(shù)據(jù)是否已經(jīng)更新,比如以前的接口回調(diào)通知可以用LiveData做到。
3.LiveData還能知曉它綁定的Activity或者Fragment的生命周期,它只會給前臺活動的組件回調(diào),避免組件銷毀后發(fā)生意想不到的崩潰情況。
那LiveData是如何做到以上這些功能的呢?
LiveData如何是如何能觀察到組件生命周期的
從使用開始入手源碼:
var myLiveData = MutableLiveData<Any>()
myLiveData.observe(this, Observer {
})
這里通過調(diào)用LiveData的observe()方法來注冊觀察者,LiveData的observe()方法如下:
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
//該方法調(diào)用者必須在主線程
assertMainThread("observe");
//如果處在DESTROYED 狀態(tài),則沒必要添加觀察者
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
//將包裝結(jié)果添加到Map里
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);
}
方法的第一個參數(shù)owner,就是注冊時的組件,即為activity或fragment,需要為實(shí)現(xiàn)LifecycleOwner接口。獲取組件當(dāng)前的生命周期狀態(tài),如果狀態(tài)為DESTROYED,那么直接return,這就保證了DESTROYED狀態(tài)的組件是不允許注冊的。
mObservers.putIfAbsent(observer, wrapper)方法將observer和LifecycleBoundObserver存儲到SafeIterableMap類型的mObservers中,putIfAbsent方法和put方法有區(qū)別,如果傳入key對應(yīng)的value已經(jīng)存在,就返回存在的value,不進(jìn)行替換。如果不存在,就添加key和value,返回null。
最后的owner.getLifecycle().addObserver(wrapper),就在LiveData內(nèi)部完成了Lifecycle的觀察者的添加,這樣LiveData就有了觀察組件生命周期變化的能力。
LiveData是如何回調(diào)observe方法的
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super 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ā)生改變時會調(diào)用onStateChanged()方法,并且判斷了當(dāng)組件處于DESTROYED狀態(tài)時,會調(diào)用removeObserver方法,來移除observer。所以當(dāng)組件銷毀時,注冊的生命周周觀察者不會再接收到通知,因?yàn)橐呀?jīng)解綁了。
shouldBeActive()用來判斷當(dāng)前宿主是否是活躍狀態(tài),此處定義的活躍狀態(tài)為:宿主的狀態(tài)要>="STARTED"狀態(tài),而該狀態(tài)區(qū)間為:Activity.onStart() 之后且Activity.onPause()之前。
當(dāng)宿主處于活躍狀態(tài)時,才會繼續(xù)通知UI 數(shù)據(jù)變更了,進(jìn)而刷新UI,若是處于非活躍狀態(tài),比如App 失去焦點(diǎn)(onPause()被調(diào)用),那么將不會刷新UI 。
通知觀察者
-
Observer的回調(diào)事件通過setValue和postValue觸發(fā)。
setValue方法:
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
從代碼中方法注解可以看出,setValue方法必須運(yùn)行在主線程中,其內(nèi)部調(diào)用了dispatchingValue方法,其后將事件通知回調(diào)給observers。
再看dispatchingValue方法:
void dispatchingValue(@Nullable ObserverWrapper initiator) {
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
//遍歷調(diào)用所有觀察者
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
在分發(fā)有效的前提下,遍歷mObservers,一次調(diào)用considerNotify()方法。
private void considerNotify(ObserverWrapper observer) {
//非活躍狀態(tài),直接返回
if (!observer.mActive) {
return;
}
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
//如果LiveData數(shù)據(jù)版本<= 觀察者的數(shù)據(jù)版本,則直接返回
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
//noinspection unchecked
observer.mObserver.onChanged((T) mData);
}
如果當(dāng)前observer的mActive值不為true,就直接return。如果判斷條件都滿足,則調(diào)用Observer接口的onChanged()方法,這個方法正是開頭myLiveData.observe(this, Observer {}) Observer接口的方法,因此完成liveData變化對observer回調(diào)事件的輪回。
public interface Observer<T> {
/**
* Called when the data is changed.
* @param t The new data
*/
void onChanged(T t);
}
postValue()
protected void postValue(T value) {
boolean postTask;
//子線程、主線程都需要修改mPendingData,因此需要加鎖
synchronized (mDataLock) {
//mPendingData 是否還在排隊(duì)等待發(fā)送出去
//mPendingData == NOT_SET 表示當(dāng)前沒有排隊(duì)
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
//說明上次的Runnable 還沒執(zhí)行
//直接返回,不需要切換到主線程執(zhí)行
return;
}
//切換到主線程執(zhí)行Runnable
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
private final Runnable mPostValueRunnable = new Runnable() {
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
//noinspection unchecked
// 切換到主線程執(zhí)行Runnable
setValue((T) newValue);
}
};
而postValue方法里,通過任務(wù)(Runnable)的方式在主線程中更新數(shù)據(jù)。而getValue中,如果livedata中mData設(shè)過值就返回mData,否則會返回null,這里在實(shí)際使用中可能會造成空指針異常。
livedata為什么連續(xù)post會丟失數(shù)據(jù)?
我們實(shí)際場景更多的是在子線程發(fā)起的,所以會用postValue來通知數(shù)據(jù)變化。
postValue里首先好會將分發(fā)的值賦值給mPendingData全局變量,然后將值的分發(fā)操作放在一個Runnable里進(jìn)行,從postValue到 ArchTaskExecutor執(zhí)行postToMainThread方法(其實(shí)里面就是mMainHandler.post(runnable))是有一個時間間隙的。
在這個時間間隙中,由于連續(xù)兩次postValue,所以mPendingData帶著第二次的最新值,進(jìn)行分發(fā),所以UI刷新,只能看到第二次的值。
其實(shí)剛才分析過程中我們也看到了,由于第二次執(zhí)行postValue的時候,mPendingData已經(jīng)不是初始值,所以導(dǎo)致postTask為false,在3處,執(zhí)行了return。所以雖然執(zhí)行了兩次postValue,可是ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable)只會執(zhí)行一次。
總結(jié)一下LiveData運(yùn)行流程:

1.通過調(diào)用LiveData的observe()方法來注冊觀察者,獲取組件當(dāng)前的生命周期狀態(tài),如果狀態(tài)為DESTROYED,那么直接return。owner.getLifecycle().addObserver(wrapper),就在LiveData內(nèi)部完成了Lifecycle的觀察者的添加,這樣LiveData就有了觀察組件生命周期變化的能力。
2.當(dāng)組件狀態(tài)發(fā)生變化時,會調(diào)用onStateChanged方法,并且判斷了當(dāng)組件處于DESTROYED狀態(tài)時,會調(diào)用removeObserver方法來移除observer。具體事件分發(fā)是通過ObserverWrapper,它是Observer的包裝類,如果是Active狀態(tài),會調(diào)用dispatchingValue方法,并將自身傳進(jìn)去。
3.在分發(fā)有效的前提下,遍歷mObservers,如果當(dāng)前observer的mActive值不為true,就直接return。如果判斷條件都滿足,則調(diào)用Observer接口的onChanged()方法。
4.最后,通過setValue和postValue方法內(nèi)部調(diào)用dispatchingValue方法,其后將事件通知回調(diào)給observers。
粘性事件
LiveData數(shù)據(jù)變更發(fā)生后,才注冊的觀察者,此時觀察者還能收到變更通知。
這和LiveData 的實(shí)現(xiàn)有關(guān),看看核心源碼實(shí)現(xiàn):
private void considerNotify(LiveData.ObserverWrapper observer) {
//mVersion 為LiveData 當(dāng)前數(shù)據(jù)版本,當(dāng)setValue/postValue 發(fā)生時,mVersion++
//通過比對LiveData 當(dāng)前數(shù)據(jù)版本與觀察者的數(shù)據(jù)版本,若是發(fā)現(xiàn)LiveData 當(dāng)前數(shù)據(jù)版本 更大
//說明是之前沒有通知過觀察者,因此需要通知,反之則不通知。
if (observer.mLastVersion >= mVersion) {
return;
}
//將觀察者數(shù)據(jù)版本保持與LiveData 版本一致,表明該觀察者消費(fèi)了最新的數(shù)據(jù)。
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}
再回溯一下流程:
1、初始時LiveData.mVersion= -1,ObserverWrapper.mLastVersion = -1,因此初次進(jìn)入Activity時沒有數(shù)據(jù)通知。
2、當(dāng)點(diǎn)擊按鈕后(LiveData.setValue()),此時LiveData.mVersion = 0;因?yàn)長iveData.mVersion>ObserverWrapper.mLastVersion,因此觀察者能夠收到通知。
3、當(dāng)退出Activity 再進(jìn)來后,因?yàn)镺bserverWrapper 是全新new 出來的,ObserverWrapper.mLastVersion = -1,而LiveData.mVersion =0,還是大于 ObserverWrapper.mLastVersion,因此依然能夠收到通知。
參考:
https://blog.csdn.net/jwg1988/article/details/122925810
https://juejin.cn/post/7081841015643963406