這是我參與更文挑戰的第17天,活動詳情查看: 更文挑戰markdown
附上一篇Livedata使用篇app
Livedata使用篇ide
不太擅長畫圖,勉強畫了一幅源碼分析
若是您對Livedata的源碼有必定了解看了這個圖應該就差很少了。post
若是對Livedata源碼瞭解很少,那麼粗略看一下圖,而後直接看後面的邏輯。看完邏輯回過頭再細看時序圖效果更佳學習
既然是源碼解析,天然入口就是咱們的方法調用,這裏簡單把註冊 Livedata 的數據監聽和 Livedata.setValue 方法進行簡單說明this
mapViewModel.mapLiveData.observe(this,{//這個回調中會收到數據更改的監聽
logEE(it)
tv_map.text=it
})
複製代碼
val userLivedata =MutableLiveData<User>()
fun sendData() {
userLivedata.value=User("李白",1200)//這句代碼發送最新數據
}
複製代碼
下一節就是 Livedata 的工做流程簡單分析了spa
我主要把代碼邏輯分爲了三部分:線程
業務代碼 Livedata.observe 註冊數據觀察code
setValue 發送最新數據
用戶視圖回到前臺自動進行數據分發
第一部分邏輯:
基本的邏輯就是咱們註冊數據監聽的時候,會傳入一個 LifeCycle 的數據監聽者接口。Livedata 的 observe 方法會將接口封裝成一個 LifecycleBoundObserver對象,而且註冊 LifeCycle 的生命週期監聽。
第二部分邏輯:
當咱們調用 Livedata.setValue 方法的時候,會逐個遍歷每個註冊的 LifecycleBoundObserver,而後分別調用 Observer 的 onChange 回調方法向咱們的業務數據監聽返回數據
第三部分邏輯:
由於咱們註冊了 LifeCycle 的生命週期,當用戶視圖回到前臺的時候會回調 LifecycleBoundObserver 的 onStateChanged 方法。onStateChanged 方法內會進行數據的分發
本節講了 Livedata 的基本邏輯,下一節主角就是代碼了
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {//若是生命週期已經被銷燬,return。這說明了使用Livedata不會發生內存泄露的緣由
// ignore
return;
}
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);//這個對象是LifecycleEventObserver的一個實現,是咱們註冊生命週期組件的觀察者
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);//將wrapper加入到map中,獲得上一個wrapper,
if (existing != null && !existing.isAttachedTo(owner)) {//isAttachedTo:上一個wrapper關聯的生命週期若是不是當前生命週期,就拋出異常
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {若是上一個wrapper不爲空就return(由於會複用上一個wrapper)
return;
}
owner.getLifecycle().addObserver(wrapper);//若是上一個爲空則說明是第一次,須要註冊生命週期監聽
}
複製代碼
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;//數據的版本,每次調用setValue都會++
mData = value;
dispatchingValue(null);//分發數據
}
複製代碼
void dispatchingValue(@Nullable ObserverWrapper initiator) {
if (mDispatchingValue) {// 一、若是正在分發中則返回
mDispatchInvalidated = true;// 二、目的是若是有新的setValue方法被調用,會在步驟4中跳出for循環,從新再進行一次分發
return;
}
mDispatchingValue = true;、// 三、設置正在分發中狀態爲true,防止1中重複進入分發消息
do {
mDispatchInvalidated = false;// 四、進入循環後設置mDispatchInvalidated爲false,若是用戶從新setValue須要將mDispatchInvalidated從新設置爲true,一邊能夠在上一輪分發結束後繼續走一輪分發
if (initiator != null) {
considerNotify(initiator);// 五、分發消息
initiator = null;
} else {
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());// 六、循環中分發消息
if (mDispatchInvalidated) {//六、若是這裏爲true說明用戶又設置了一次value,那麼跳出for循環,從新執行外層的dowhile循環
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;//七、消息分發完成,設置正在分發中狀態爲false
}
複製代碼
3.經過分析,咱們發現 dispatchingValue 方法內最終再次分發消息的方法是 considerNotify,方法體:
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {//一、若是當前lifecycle不是活躍狀態就返回不進行消息分發,銷燬會在生命週期最近變活躍的時候自動分發
return;
}
if (!observer.shouldBeActive()) {//二、若是lifecycle狀態爲started||resumed
observer.activeStateChanged(false);//三、激活狀態,activeStateChanged方法裏面會再次調用dispatchValue分發消息,通常用做livedata從不活躍狀態回到活躍狀態的時候自動分發消息
return;
}
if (observer.mLastVersion >= mVersion) {//四、若是true,說明第6步中有更小版本的消息正在調用,因此返回
return;
}
observer.mLastVersion = mVersion;//五、記住當前正在分發value的版本,用於第四部中的邏輯判斷
observer.mObserver.onChanged((T) mData);//六、調用註冊livedata的observer的onChanged通知用戶更新數據
}
複製代碼
considerNotify 方法中調用了 mObserver.onChanged 後就會回調咱們業務代碼中的消息註冊監聽,整個數據流轉的邏輯就完成了
邏輯同 Livedata.setValue
咱們知道咱們是經過 LifeCycle 生命週期組件來監聽生命週期的。
監聽生命週期的接口實現就是 LifecycleBoundObserver 類,當生命週期發生改變的時候會回調 LifecycleBoundObserver 類的方法 onStateChanged:
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
if (currentState == DESTROYED) {//若是生命週期已經銷燬,那麼移除監聽者
removeObserver(mObserver);
return;
}
Lifecycle.State prevState = null;
while (prevState != currentState) {//回調的生命週期狀態和當前不一樣,則進行數據回調
prevState = currentState;
activeStateChanged(shouldBeActive());//這個方法是關鍵,他內部會進行數據的分發
currentState = mOwner.getLifecycle().getCurrentState();//重置生命週期狀態
}
}
複製代碼
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
mActive = newActive;
changeActiveCounter(mActive ? 1 : -1);
if (mActive) {
dispatchingValue(this);//看到這裏你直接去找上一節Livedata.setValue的源碼分析就ok了
}
}
複製代碼
實際沒啥好說的,就是將線程切回到主線程,而後調用 Livedata.setValue 更新數據而已。
最後,更重要的在下面:
關注個人公衆號 「安安安安卓」 學習更多知識