Android Jetpack之LiveData源碼分析

什么是LiveData

android開發(fā)者官網(wǎng)上對其的定義是:LiveData 是一種可觀察的數(shù)據(jù)存儲器類。與常規(guī)的可觀察類不同,LiveData 具有生命周期感知能力,意指它遵循其他應用組件(如 Activity、Fragment 或 Service)的生命周期。這種感知能力可確保 LiveData 僅更新處于活躍生命周期狀態(tài)的應用組件觀察者。上面這段話概括起來包括下面四個特點:

  • 是一個數(shù)據(jù)持有類
  • 能夠感知組件的生命周期
  • 數(shù)據(jù)可以被觀察者觀察
  • 只有在組件處于激活狀態(tài)才會通知觀察者有數(shù)據(jù)更新

如何使用

下面是一個簡單的例子:

public class MutableLiveDataActivity extends AppCompatActivity  {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mutable_live_data);

        ConstraintLayout layout = findViewById(R.id.layout);
        // new一個MutableLiveData對象,MutableLiveData是LiveData的子類
        final MutableLiveData<String> livedata = new MutableLiveData<>();
        // 注冊和宿主生命周期關聯(lián)的觀察者
        livedata.observe(this, new Observer<String>() {
            @Override
            public void onChanged(String str) {
                // 當數(shù)據(jù)發(fā)生變化時或者宿主生命周期發(fā)生變化時回調(diào)
                Log.e("TAG", String.valueOf(str));
            }
        });

        layout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 發(fā)送數(shù)據(jù),沒有活躍的觀察者時不分發(fā)。只能在主線程。
                livedata.setValue("測試");
                // 發(fā)送數(shù)據(jù),沒有活躍的觀察者時不分發(fā)??梢栽谌我饩€程。
                livedata.postValue("測試");
            }
        });

    }
}

源碼分析

下面通過分析源碼來詳細看一看LiveData到底是如何實現(xiàn)上面提到這個點的。
首先點開observe方法,進入到LiveData類看一下observe實現(xiàn)了什么功能,
LiveData.java

   @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        assertMainThread("observe");  // 判斷是否在主線程
        // 判斷生命周期的宿主(通常就是activity, fragment, service)當前的狀態(tài)是否已銷毀
       //  如果是,則直接return,后面的代碼不用執(zhí)行了
        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);
    }

LifecycleBoundObserver內(nèi)部類 繼承了ObserverWrapper抽象類并實現(xiàn)了GenericLifecycleObserver接口。主要實現(xiàn)宿主生命周期與觀察者之間的綁定,比較關鍵的是onStateChanged方法。

class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
        @NonNull
        final LifecycleOwner mOwner;

        LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
            super(observer);
            mOwner = owner;
        }

        @Override
        boolean shouldBeActive() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }
        
        /**
         * LifecycleEventObserver感知生命周期的回調(diào),當宿主生命周期發(fā)生變化時回調(diào)。
         */
        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            // 先判斷宿主生命周期狀態(tài)是否是DESTROYED,如果如果已經(jīng)銷毀,則移除觀察者。
            // 這里顯示出了LiveData不會發(fā)生內(nèi)存泄漏的優(yōu)勢,觀察者會綁定到Lifecycle對象,并在其關聯(lián)的生命周期遭到銷毀后進行自我清理
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
            // 活動狀態(tài)發(fā)生變化的時候調(diào)用,這里shouldBeActive()的返回值是當LifecycleOwner的狀態(tài)是STARTED或者RESUMED時為true,其他狀態(tài)為false
            activeStateChanged(shouldBeActive());
        }

        @Override
        boolean isAttachedTo(LifecycleOwner owner) {
            return mOwner == owner;
        }

        @Override
        void detachObserver() {
            mOwner.getLifecycle().removeObserver(this);
        }
    }

ObserverWrapper內(nèi)部抽象類,核心方法是dispatchingValue,當宿主處于活躍狀態(tài)時,調(diào)用dispatchingValue()

private abstract class ObserverWrapper {

        ...
        
        /**
         * 宿主狀態(tài)發(fā)生改變
         */ 
        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);
            }
        }
    }

dispatchingValue(),核心內(nèi)容是do while循環(huán)中,調(diào)用considerNotify()來通知觀察者調(diào)用onChanged方法

void dispatchingValue(@Nullable ObserverWrapper initiator) {
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        // 核心部分是do  while中的循環(huán)操作
        do {
            mDispatchInvalidated = false;
            // 先判斷ObserverWrapper是否為null,從源碼中我們可以發(fā)現(xiàn),當宿主生命周期發(fā)生變化時,這里ObserverWrapper是傳入了值了的,當調(diào)用LiveData的setValue()時,傳入的是null
            if (initiator != null) {
                considerNotify(initiator);
                initiator = null;
            } else {
                // mObservers可以看做是一個可迭代的map,其中存放了所有添加進去的觀察者
                // 這里是遍歷所有的觀察者,然后調(diào)用considerNotify()
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }

considerNotify ,這里做了三重判斷之后,調(diào)用觀察者的onChanged()方法。

private void considerNotify(ObserverWrapper observer) {
        // 判斷觀察者是否在活躍狀態(tài)
        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.
        // 判斷宿主生命周期是否處于活躍狀態(tài)(STARTED或者RESUMED狀態(tài))
        if (!observer.shouldBeActive()) {
            // 如果宿主生命周期處于非活躍的狀態(tài),那么調(diào)用activeStateChanged()
            observer.activeStateChanged(false);
            return;
        }
        // mVersion記錄了setValue調(diào)用的次數(shù),這里對版本號的比較有效的防止了宿主生命周期發(fā)生變化時observer會調(diào)用onChanged()的情況。
        // 例如屏幕旋轉時,activity的生命周期發(fā)生了變化,在調(diào)用此方法時,由于這里mLastVersion和mVersion值相同,所以直接return,并不會執(zhí)行observer的onChanged方法
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        // observer調(diào)用onChanged()
        observer.mObserver.onChanged((T) mData);
    }

??通過上面的源碼分析之后可以看到LiveData在注冊了觀察者之后做了哪些事情,也凸顯了上面一開始介紹的夠感知組件的生命周期只有在組件處于激活狀態(tài)才會通知觀察者有數(shù)據(jù)更新的特點。下面接著來看一下LiveData在setValue/postValue之后做了什么:
setValue 首先判斷了程序是否處在主線程中(與postValue有不同),之后調(diào)用了dispatchingValue()方法并傳入了一個null值。之后的流程就是上面分析過的流程了,只不過傳入的數(shù)據(jù)不同。

    @MainThread
    protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }

這里開看一下它是怎么持有數(shù)據(jù)的,setValue需要傳入的值value是一個泛型,之后這個值被賦給了mData,mData是一個Object類型的數(shù)據(jù),之后在considerNotify方法中調(diào)用observer的onChanged方法時將mData傳入:
observer.mObserver.onChanged((T) mData);
看完了setValue方法,也順帶著看一下postValue,看看兩者之間有什么區(qū)別:

protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            // 將value賦值給了mPendingData,這里是跟setValue不同點之一
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
        // 在主線程中去執(zhí)行,這里是不同點二
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }

從上下兩段代碼可以看出,setValue是必須要到主線程中執(zhí)行的,而postValue可以在主線程或者子線程中執(zhí)行,至于為什么在postValue中增加了一個mPendingData變量,而不是用之前的mData變量,我覺得應該是怕在多線程中引起數(shù)據(jù)錯亂的原因,所以在當前線程中將value賦值給mPendingData,然后在主線程中將mPendingData的值再賦給mData。

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容