Livedata源碼詳細解析-面試這麼講就ok

這是我參與更文挑戰的第17天,活動詳情查看: 更文挑戰markdown

附上一篇Livedata使用篇app

Livedata使用篇ide

時序圖

不太擅長畫圖,勉強畫了一幅源碼分析

若是您對Livedata的源碼有必定了解看了這個圖應該就差很少了。post

若是對Livedata源碼瞭解很少,那麼粗略看一下圖,而後直接看後面的邏輯。看完邏輯回過頭再細看時序圖效果更佳學習

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 代碼邏輯

我主要把代碼邏輯分爲了三部分:線程

  1. 業務代碼 Livedata.observe 註冊數據觀察code

  2. setValue 發送最新數據

  3. 用戶視圖回到前臺自動進行數據分發

第一部分邏輯:

基本的邏輯就是咱們註冊數據監聽的時候,會傳入一個 LifeCycle 的數據監聽者接口。Livedata 的 observe 方法會將接口封裝成一個 LifecycleBoundObserver對象,而且註冊 LifeCycle 的生命週期監聽。

第二部分邏輯:

當咱們調用 Livedata.setValue 方法的時候,會逐個遍歷每個註冊的 LifecycleBoundObserver,而後分別調用 Observer 的 onChange 回調方法向咱們的業務數據監聽返回數據

第三部分邏輯:

由於咱們註冊了 LifeCycle 的生命週期,當用戶視圖回到前臺的時候會回調 LifecycleBoundObserver 的 onStateChanged 方法。onStateChanged 方法內會進行數據的分發

本節講了 Livedata 的基本邏輯,下一節主角就是代碼了

結合代碼講解邏輯

註冊 Livedata 監聽

  1. observe 方法體
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);//若是上一個爲空則說明是第一次,須要註冊生命週期監聽
    }
複製代碼

Livedata.setValue

  1. 首先看一下 setValue 方法體:
protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;//數據的版本,每次調用setValue都會++
        mData = value;
        dispatchingValue(null);//分發數據
    }
複製代碼
  1. 咱們發現發法最後調用了 dispatchingValue 方法,那麼就再看一下 dispatchingValue 方法體吧
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:

  1. 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();//重置生命週期狀態
            }
        }
複製代碼
  1. activeStateChanged 方法體
void activeStateChanged(boolean newActive) {
            if (newActive == mActive) {
                return;
            }
            mActive = newActive;
            changeActiveCounter(mActive ? 1 : -1);
            if (mActive) {
                dispatchingValue(this);//看到這裏你直接去找上一節Livedata.setValue的源碼分析就ok了
            }
        }
複製代碼

postValue

實際沒啥好說的,就是將線程切回到主線程,而後調用 Livedata.setValue 更新數據而已。

最後,更重要的在下面:

關注個人公衆號 「安安安安卓」 學習更多知識

相關文章
相關標籤/搜索