一、什麼是 LiveData
git
LiveData
是一個數據持有類。它具備如下特色:github
二、LiveData 能爲咱們作什麼安全
可以保證 數據 和 UI
統一。LiveData
採用了 觀察者模式,LiveData
是被觀察者,當數據有變化時會通知 UI
。架構
減小內存泄露。LiveData
可以感知到組件的生命週期,當組件處於 銷燬(destroyed
) 狀態時,觀察者對象會被清除,當 Activity
中止時不會致使 crash
,由於 組件處於非激活狀態時,不會收到 LiveData
中數據變化的通知。app
組件和數據相關的內容可以實時更新。組件在前臺的時候可以實時收到數據改變的通知,當組件從後臺切換到前臺時,LiveData
可以將最新的數據通知組件,所以保證了組件中和數據相關的內容可以實時更新。ide
解決橫豎屏切換(configuration change
)數據問題。在屏幕發生旋轉時,不須要額外的處理來保存數據,當屏幕方向變化時,組件會被 recreate
,然而系統並不能保證你的數據可以被恢復。當採用 LiveData
保存數據時,由於數據和組件分離了,當組件被 recreate
,數據仍是存在 LiveData
中,並不會被銷燬。源碼分析
資源共享。若是對應的 LiveData
是單例的話,就能在 App
的組件間分享數據;這部分詳細的信息能夠參考 繼承 LiveData
。post
LiveData
LiveData
的2種建立方式:this
MutableLiveData
對象;LiveData
類。1.一、直接使用 MutableLiveData
spa
MutableLiveData<String> data = new MutableLiveData<>();
1.二、繼承 LiveData
LiveData
經過 observe()
方法註冊觀察者。觀察者這裏使用匿名方式:
// 寫於MainActivity data.observe(this, new Observer<String>() { @Override public void onChanged(@Nullable String s) { Toast.makeText(MainActivity.this,s,Toast.LENGTH_SHORT).show(); } });
Observe() 源碼分析:
@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
和 觀察者。看下源碼: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); } }
LifecycleBoundObserver
繼承自 ObserverWrapper
,並實現 GenericLifecycleObserver
,而 GenericLifecycleObserver
繼承了 LifecycleObserver
接口。
由此能夠看出LifecycleBoundObserver
類就是把Observer
和生命週期關聯起來。
再看此類,咱們先看 onStateChanged()
方法,當生命週期變化時會回調,若是getCurrentState() == DESTROYED
則 removeObserver
,反之則調用父類ObserverWrapper
的activeStateChanged()
方法:
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);
應該就是數據變化消息調度。源代碼:
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)
方法;源代碼:
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
,咋們再看看在哪兒存的:
回到 Observe() 方法中:
@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); }
mObservers.putIfAbsent(observer, wrapper)
存入容器中,mObservers.putIfAbsent
這個添加數據的方式貌似不多見,因而乎在看看 mObservers
是個什麼數據容器,成員變量中:
private SafeIterableMap<Observer<T>, ObserverWrapper> mObservers = new SafeIterableMap<>();
SafeIterableMap
有如下特性:
Map
的接口ConcurrentModifiedException
最後 addObserver
添加註冊。
發起數據通知 2 種方式:
postValue
setValue
data.postValue("Hello LiveData"); // data.setValue("Hello LiveData");
MutableLiveData
源碼:
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
代碼:
@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"); } }
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
。
LiveDataBus
的設計和架構LiveDataBus
的組成消息 消息能夠是任何的Object
,能夠定義不一樣類型的消息,如Boolean
、String
。也能夠定義自定義類型的消息。
消息通道
LiveData
扮演了消息通道的角色,不一樣的消息通道用不一樣的名字區分,名字是String
類型的,能夠經過名字獲取到一個LiveData
消息通道。
消息總線
消息總線經過單例實現,不一樣的消息通道存放在一個HashMap
中。
訂閱
訂閱者經過getChannel
獲取消息通道,而後調用observe
訂閱這個通道的消息。
發佈
發佈者經過getChannel
獲取消息通道,而後調用setValue
或者postValue
發佈消息。