您好,登錄后才能下訂單哦!
前言
最近的項目重構(gòu)中加入LiveData框架,并且小碼的T-MVVM也是用了LiveData框架,好不好用你試試就知道(小碼口頭禪),對于LiveData使用的時候并未做太多的理解,于是乎翻了翻LiveData源代碼,在此做下筆記,
什么是LiveData
LiveData是一個數(shù)據(jù)持有類。它具有以下特點:
LiveData能為我們做什么
接下來先從使用玩起,
繼承LiveData類,如MutableLiveData,
發(fā)起數(shù)據(jù)通知2種方式:postValue和setValue:
private MutableLiveData<String> mData=new MutableLiveData();
mBookData.postValue("Hello LiveData");
// mBookData.setValue("Hello LiveData");
此處postValue和setValue的區(qū)別,下文會提,
注冊觀察者并監(jiān)聽數(shù)據(jù)變化:
mData.observe(this, new Observer<String>() {
@Override
public void onChanged(@Nullable String str) {
Toast.makeText(this, str, Toast.LENGTH_SHORT).show();
}
});
使用非常簡單,僅此而已
通過observe方法注冊觀察者,哪咋們就看看observe里面具體干了什么,源代碼165行走起,
//注冊觀察
@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方法接收2個參數(shù),一個是具有生命周期的LifecycleOwner,另一個是觀察者Observer<T> ,首先判斷LifecycleOwner當(dāng)前的生命周期是否為Destroyed,如果是則直接 return;如果不等于Destroyed,接下來往下看, 此處new了一個內(nèi)部類LifecycleBoundObserver對象并且構(gòu)造方法傳入了具有生命周期的LifecycleOwner和觀察者,這是個什么鬼,看看他的具體方法,LifecycleBoundObserver繼承自O(shè)bserverWrapper,并實現(xiàn)GenericLifecycleObserver,而GenericLifecycleObserver繼承了LifecycleObserver接口。由此可以看出LifecycleBoundObserver類就是把Observer和生命周期關(guān)聯(lián)起來,ok,那我們先看看LifecycleBoundObserver方法,源代碼349行走起,
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);
}
}
此方法中,我們先看onStateChanged()方法,當(dāng)生命周期變化時會回調(diào),如果getCurrentState() == DESTROYED則removeObserver,反之則調(diào)用父類ObserverWrapper的activeStateChanged()方法,源代碼382行走起,
private abstract class ObserverWrapper {
final Observer<T> mObserver;
boolean mActive;
int mLastVersion = START_VERSION;
ObserverWrapper(Observer<T> observer) {
mObserver = observer;
}
abstract boolean shouldBeActive();
boolean isAttachedTo(LifecycleOwner owner) {
return false;
}
void detachObserver() {
}
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);
}
}
}
activeStateChanged()是干嘛的,首先判斷activeState新舊狀態(tài)是否相同,不同則把新的狀態(tài)賦給mActive,是生命周期狀態(tài)處于ACTIVE情況下的邏輯處理。如果新的狀態(tài)和舊的狀態(tài)相同則直接返回。這里有個常量LiveData.this.mActiveCount,看注釋可以理解為觀察者處于活動狀態(tài)
個數(shù),往下看 if (wasInactive && mActive)如果mActiveCount=0并且mActive為true,即觀察者處于活動狀態(tài)
個數(shù)從0變?yōu)?個則調(diào)用onActive(); 觀察者處于活動狀態(tài)
個數(shù)從1變?yōu)?時則調(diào)用onInactive()。然而onActive(),onInactive()并沒有任何實現(xiàn)代碼。好了,接下來繼續(xù)往下看dispatchingValue(this);應(yīng)該就是數(shù)據(jù)變化消息調(diào)度。源代碼112行走起,
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;
}
前面的幾行if 判斷姑且先不看,先看從if(initiator != null)開始看,如果initiator!= null調(diào)用considerNotify(initiator)方法;源代碼91行走起,
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);
}
看見沒有最后一行代碼 observer.mObserver.onChanged((T) mData); Observer的數(shù)據(jù)變化回調(diào);好了我們再回過頭看看initiator == null的邏輯,
for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
如果initiator == null 則會通過迭代器mObservers遍歷獲取ObserverWrapper,最終還是調(diào)用considerNotify方法;既然有取ObserverWrapper,咋們再看看在哪兒存的,在源碼171行:
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);
mObservers.putIfAbsent(observer, wrapper)存入容器中,mObservers.putIfAbsent這個添加數(shù)據(jù)的方式貌似很少見,于是乎在看看mObservers是個什么數(shù)據(jù)容器,成員變量中:
private SafeIterableMap<Observer<T>, ObserverWrapper> mObservers =
new SafeIterableMap<>();
這是個什么鬼,貌似以前很少見,查閱資料發(fā)現(xiàn):
SafeIterableMap有以下特性:
1;支持鍵值對存儲,用鏈表實現(xiàn),模擬成Map的接口
2:支持在遍歷的過程中刪除任意元素,不會觸發(fā)ConcurrentModifiedException
3:非線程安全
感興趣的可自行查閱,此處不再詳細(xì)介紹,
最后addObserver添加注冊。
下面在看看數(shù)據(jù)發(fā)起通知的邏輯,數(shù)據(jù)發(fā)起通知有2中方式:
public class MutableLiveData<T> extends LiveData<T> {
@Override
public void postValue(T value) {
super.postValue(value);
}
@Override
public void setValue(T value) {
super.setValue(value);
}
}
setValue和postValue2中方式,我們先看看setValue代碼:
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
private static void assertMainThread(String methodName) {
if (!ArchTaskExecutor.getInstance().isMainThread()) {
throw new IllegalStateException("Cannot invoke " + methodName + " on a background"
+ " thread");
}
}
setValue第一行代碼 assertMainThread("setValue");則是判斷是否在主線程,所以貌似setValue方式必須在主線程中執(zhí)行,如果非主線程則拋出異常。
再看看postValue:
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
則postValue調(diào)用postToMainThread方法,最終還是用過setValue方式:
private final Runnable mPostValueRunnable = new Runnable() {
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
//noinspection unchecked
setValue((T) newValue);
}
};
因此最終明白為什么setValue方法只能在主線程中調(diào)用,postValue可以在任何線程中調(diào)用,如果是在后臺子線程中更新LiveData的值,必須調(diào)用postValue。
至此大概明白了LiveData是干嘛的 ,怎么干的,總的來說還是很好用的,于是乎就有個小小的想法,平時用Eventbus,RxBus什么的,貌似感覺LiveData也可以實現(xiàn)事件總線,既然有了想法,那就干唄,
/**
* 事件總線
*
* @author:tqzhang on 18/9/11 17:22
*/
public class LiveBus {
private static volatile LiveBus instance;
private final Map<Object, MutableLiveData<Object>> mLiveBus;
private LiveBus() {
mLiveBus = new HashMap<>();
}
public static LiveBus getDefault() {
if (instance == null) {
synchronized (LiveBus.class) {
if (instance == null) {
instance = new LiveBus();
}
}
}
return instance;
}
/**
*
* subscriber 注冊時間 key
*/
public <T> MutableLiveData<T> subscribe(Object subscriber, Class<T> tMutableLiveData) {
checkNotNull(subscriber);
checkNotNull(tMutableLiveData);
if (!mLiveBus.containsKey(subscriber)) {
mLiveBus.put(subscriber, new MutableLiveData<>());
}
return (MutableLiveData<T>) mLiveBus.get(subscriber);
}
}
簡單的50行代碼實現(xiàn)類似Eventbus,RxBus的功能,小碼親測了,挺好使的。
//發(fā)起通知
LiveBus.getDefault().subscribe("livedata",String.class).postValue("hello LiveData");
//注冊觀察
LiveBus.getDefault().subscribe("livedata",String.class).observe(this, new Observer<String>() {
@Override
public void onChanged(@Nullable String s) {
Toast.makeText(activity, s, Toast.LENGTH_SHORT).show();
}
});
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。