您好,登錄后才能下訂單哦!
前言
最近的項目重構中加入LiveData框架,并且小碼的T-MVVM也是用了LiveData框架,好不好用你試試就知道(小碼口頭禪),對于LiveData使用的時候并未做太多的理解,于是乎翻了翻LiveData源代碼,在此做下筆記,
什么是LiveData
LiveData是一個數據持有類。它具有以下特點:
LiveData能為我們做什么
接下來先從使用玩起,
繼承LiveData類,如MutableLiveData,
發起數據通知2種方式:postValue和setValue:
private MutableLiveData<String> mData=new MutableLiveData();
mBookData.postValue("Hello LiveData");
// mBookData.setValue("Hello LiveData");
此處postValue和setValue的區別,下文會提,
注冊觀察者并監聽數據變化:
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個參數,一個是具有生命周期的LifecycleOwner,另一個是觀察者Observer<T> ,首先判斷LifecycleOwner當前的生命周期是否為Destroyed,如果是則直接 return;如果不等于Destroyed,接下來往下看, 此處new了一個內部類LifecycleBoundObserver對象并且構造方法傳入了具有生命周期的LifecycleOwner和觀察者,這是個什么鬼,看看他的具體方法,LifecycleBoundObserver繼承自ObserverWrapper,并實現GenericLifecycleObserver,而GenericLifecycleObserver繼承了LifecycleObserver接口。由此可以看出LifecycleBoundObserver類就是把Observer和生命周期關聯起來,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()方法,當生命周期變化時會回調,如果getCurrentState() == DESTROYED則removeObserver,反之則調用父類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新舊狀態是否相同,不同則把新的狀態賦給mActive,是生命周期狀態處于ACTIVE情況下的邏輯處理。如果新的狀態和舊的狀態相同則直接返回。這里有個常量LiveData.this.mActiveCount,看注釋可以理解為觀察者處于活動狀態
個數,往下看 if (wasInactive && mActive)如果mActiveCount=0并且mActive為true,即觀察者處于活動狀態
個數從0變為1個則調用onActive(); 觀察者處于活動狀態
個數從1變為0時則調用onInactive()。然而onActive(),onInactive()并沒有任何實現代碼。好了,接下來繼續往下看dispatchingValue(this);應該就是數據變化消息調度。源代碼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調用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的數據變化回調;好了我們再回過頭看看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,最終還是調用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這個添加數據的方式貌似很少見,于是乎在看看mObservers是個什么數據容器,成員變量中:
private SafeIterableMap<Observer<T>, ObserverWrapper> mObservers =
new SafeIterableMap<>();
這是個什么鬼,貌似以前很少見,查閱資料發現:
SafeIterableMap有以下特性:
1;支持鍵值對存儲,用鏈表實現,模擬成Map的接口
2:支持在遍歷的過程中刪除任意元素,不會觸發ConcurrentModifiedException
3:非線程安全
感興趣的可自行查閱,此處不再詳細介紹,
最后addObserver添加注冊。
下面在看看數據發起通知的邏輯,數據發起通知有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方式必須在主線程中執行,如果非主線程則拋出異常。
再看看postValue:
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
則postValue調用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方法只能在主線程中調用,postValue可以在任何線程中調用,如果是在后臺子線程中更新LiveData的值,必須調用postValue。
至此大概明白了LiveData是干嘛的 ,怎么干的,總的來說還是很好用的,于是乎就有個小小的想法,平時用Eventbus,RxBus什么的,貌似感覺LiveData也可以實現事件總線,既然有了想法,那就干唄,
/**
* 事件總線
*
* @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行代碼實現類似Eventbus,RxBus的功能,小碼親測了,挺好使的。
//發起通知
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();
}
});
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。