4. Jetpack源碼解析—LiveData的使用及工做原理

1. 背景

上一篇咱們分析了Lifecycles組件的源碼,本篇咱們將繼續分析LiveData組件java

相關係列文章:git

1. Jetpack源碼解析---看完你就知道Navigation是什麼了?github

2. Jetpack源碼解析---Navigation爲何切換Fragment會重繪?app

3. Jetpack源碼解析---用Lifecycles管理生命週期異步

2. 基礎

2.1 簡介

LiveData是一個可觀察的數據持有者類,與常規observable不一樣,LiveData是生命週期感知的,這意味着它尊重其餘應用程序組件的生命週期,例如ActivityFragmentService。此感知確保LiveData僅更新處於活動生命週期狀態的應用程序組件觀察者。ide

2.2 優勢

1. 確保UI符合數據狀態 LiveData遵循觀察者模式。 當生命週期狀態改變時,LiveData會向Observer發出通知。 您能夠把更新UI的代碼合併在這些Observer對象中。沒必要去考慮致使數據變化的各個時機,每次數據有變化,Observer都會去更新UI。函數

2. 沒有內存泄漏 Observer會綁定具備生命週期的對象,並在這個綁定的對象被銷燬後自行清理。源碼分析

3. 不會因中止Activity而發生崩潰 若是Observer的生命週期處於非活躍狀態,例如在後退堆棧中的Activity,就不會收到任何LiveData事件的通知。post

4.不須要手動處理生命週期 UI組件只須要去觀察相關數據,不須要手動去中止或恢復觀察。LiveData會進行自動管理這些事情,由於在觀察時,它會感知到相應組件的生命週期變化。ui

5. 始終保持最新的數據 若是一個對象的生命週期變到非活躍狀態,它將在再次變爲活躍狀態時接收最新的數據。 例如,後臺Activity在返回到前臺後當即收到最新數據。

6. 正確應對配置更改 若是一個Activity或Fragment因爲配置更改(如設備旋轉)而從新建立,它會當即收到最新的可用數據。

7.共享資源 您可使用單例模式擴展LiveData對象幷包裝成系統服務,以便在應用程序中進行共享。LiveData對象一旦鏈接到系統服務,任何須要該資源的Observer都只需觀察這個LiveData對象。

2.3 基本使用

在咱們的Jetpack_Note中有使用demo,具體可查看LiveDataFragment。 Demo中經過對一個LiveData對象進行生命週期的監聽,實現將值打印在控制檯中。首先聲明一個LiveData對象:

private lateinit var liveData: MutableLiveData<String>
複製代碼

點擊開始觀察數據按鈕,彈出控制檯,咱們能夠看到控制檯輸出了onStart()日誌,由於咱們將liveData的值和Fragment的生命週期進行了綁定,當返回桌面或者銷燬Fragment的時候,LiveData的值會變成相應的生命週期函數,並打印在控制檯中:

class LiveDataFragment : Fragment() {

    private lateinit var liveData: MutableLiveData<String>

    override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? {
        return inflater.inflate(R.layout.fragment_live_data, container, false)
    }


    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        liveData = MutableLiveData()
        btn_observer_data.setOnClickListener {
            if (FloatWindow.get() == null) {
                FloatWindowUtils.init(activity?.application!!)
            }
            FloatWindowUtils.show()

            //建立一個觀察者去更新UI
            val statusObserver = Observer<String> { lifeStatus ->
                FloatWindowUtils.addViewContent("LiveData-onChanged: $lifeStatus")
            }
            liveData.observeForever(statusObserver)
        }
    }


    override fun onStart() {
        super.onStart()
        liveData.value = "onStart()"
    }


    override fun onPause() {
        super.onPause()
        liveData.value = "onPause()"
    }

    override fun onStop() {
        super.onStop()
        liveData.value = "onStop()"
    }

    override fun onDestroy() {
        super.onDestroy()
        liveData.value = "onDestroy()"
    }
}
複製代碼

**注意:**這裏我使用了observeForever監聽了全部生命週期方法,因此你會看到onDestroy()等生命週期函數的打印。

好了,Demo很簡單,接下來咱們來看一下源碼,進行分析:

3. 源碼分析:

3.1 observer()

咱們聲明瞭一個LiveData對象,並經過監聽Fragment的生命週期來改變LiveData中的value值,LiveData實際上就像一個容器,Demo中存儲了一個String類型的值,當這個值發生改變的時候,能夠在回調中監聽到他的改變。接下來咱們就先從addObserver入手:

@MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        assertMainThread("observe");
        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);
    }
複製代碼

查看源碼,咱們調用observer()時,傳遞了兩個參數,第一個是LifecycleOwner接口實例,而咱們繼承的Fragment自己就已經實現了這個接口,因此咱們傳this便可;第二個參數Observer就是咱們觀察的回調。接下來將這兩個參數傳遞new出了一個新的對象:LifecycleBoundObserver,最後將LifecycleBoundObserverLifecycleOwner進行了綁定,其實這裏面咱們能夠將LifecycleOwner就理解成咱們的Fragment或者Activity的實例,由於它們都實現了LifecycleOwner

3.2 LifecycleBoundObserver

class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
        .....
        @Override
        boolean shouldBeActive() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }
        //Activity生命週期變化時,回調方法
        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
            //更新livedata活躍狀態
            activeStateChanged(shouldBeActive());
        }

        @Override
        boolean isAttachedTo(LifecycleOwner owner) {
            return mOwner == owner;
        }
        //解除監聽
        @Override
        void detachObserver() {
            mOwner.getLifecycle().removeObserver(this);
        }
    }
複製代碼

咱們能夠看到這裏面與LifecycleOwner進行了綁定,而且實現了onStateChanged方法,當生命週期發生變化時執行activeStateChanged(shouldBeActive());方法;shouldBeActive() 返回了 要求生命週期至少是STARTED狀態才被認爲是activie狀態;若是state是DESTROYED狀態時,解綁LifecycleOwnerLiveData。接下來咱們看下怎樣更新livedata中數據值:

3.3 dispatchingValue()

咱們追蹤activeStateChanged方法發現,在裏面作了一些活躍狀態值的操做,而且當狀態活躍時,更新數據值:

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);
            }
        }
複製代碼
void dispatchingValue(@Nullable ObserverWrapper initiator) {
    ...
    //遍歷LiveData的全部觀察者執行下面代碼
    for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
    ...
}
//將數據值回調到livedata.observer()回去
private void considerNotify(ObserverWrapper observer) {
        if (!observer.mActive) {
            return;
        }
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        observer.mObserver.onChanged((T) mData);
    }
複製代碼

從上面咱們能夠看到LiveData的數據更新以及數據回調的整個過程,可是當咱們手動setValue()的時候過程是怎樣的呢?你會發現,setValue()其實最後就是經過調用了dispatchingValue()方法。而關於postValue()在子線程更新數據的相關代碼,這裏就不作介紹了,其實你大能夠想出來,就是使用的Handler

LiveData中的代碼很簡潔,400多行的代碼,看起來也並不費勁,下面咱們來分析下整個流程:

  • 經過使用LiveData對象,爲它建立觀察者Observer
  • 建立Observer時綁定Fragment生命週期
  • LifecycleBoundObserver生命週期變化時,dispatchValue下發更新LiveData中的值
  • LiveData主動setValue時,會主動dispatchValue,而且會considerNotify激活observer

4. 擴展

4.1 Map轉換

咱們在開發中常常會遇到這種場景,有時咱們須要根據另一個LiveData實例返不一樣的LiveData實例,而後在分發給Observer,Lifecycle包提供了Transformations類,能夠幫助咱們實現這樣的場景:

經過**Transformations.map()**使用一個函數來轉換存儲在 LiveData對象中的值,並向下傳遞轉換後的值:

LiveDataViewModel

class LiveDataViewModel : ViewModel() {
    val data = listOf(User(0,"Hankkin"), User(1,"Tony"),User(2,"Bob"),User(3,"Lucy"))

    val id = MutableLiveData<Int>()
    //map轉換返回User實體
    val bean: LiveData<User> = Transformations.map(id, Function {
        return@Function findUserById(id.value!!)
    })
    //根據id查找User
    private fun findUserById(id: Int): User? {
        return data.find { it.id == id }
    }
}
複製代碼

LiveDataFragment

//改變ViewModel中idLiveData中的值
        btn_observer_map.setOnClickListener {
            mId++
            viewModel.id.postValue(mId)
        }
        //當idLiveData變化後,UserBean也會改變且更新Textview的文本
        viewModel.bean.observe(
            this,
            Observer { tv_livedata_map.text = if (it == null) "未查找到User" else "爲你查找到的User爲:${it.name}" })
複製代碼

4.2 Map源碼

@MainThread
    public static <X, Y> LiveData<Y> map( @NonNull LiveData<X> source, @NonNull final Function<X, Y> mapFunction) {
        final MediatorLiveData<Y> result = new MediatorLiveData<>();
        result.addSource(source, new Observer<X>() {
            @Override
            public void onChanged(@Nullable X x) {
                result.setValue(mapFunction.apply(x));
            }
        });
        return result;
    }
複製代碼

咱們能夠看到map的源碼是經過MediatorLiveData中的addSource()方法來實現的,第一個參數爲咱們須要改變的LiveData值,也就是咱們上面例子中的userid,第二個參數則是咱們傳過來的Fuction經過高階函數,將值set到LiveData上。

下面咱們看下addSource()方法:

@MainThread
    public <S> void addSource(@NonNull LiveData<S> source, @NonNull Observer<? super S> onChanged) {
        Source<S> e = new Source<>(source, onChanged);
        Source<?> existing = mSources.putIfAbsent(source, e);
        if (existing != null && existing.mObserver != onChanged) {
            throw new IllegalArgumentException(
                    "This source was already added with the different observer");
        }
        if (existing != null) {
            return;
        }
        if (hasActiveObservers()) {
            e.plug();
        }
    }
複製代碼

這裏把咱們的LiveData和Observer封裝成了Source對象,而且這個對象,不能重複添加,具體代碼可查看Source:

private static class Source<V> implements Observer<V> {
        final LiveData<V> mLiveData;
        final Observer<? super V> mObserver;
        int mVersion = START_VERSION;

        Source(LiveData<V> liveData, final Observer<? super V> observer) {
            mLiveData = liveData;
            mObserver = observer;
        }

        void plug() {
            mLiveData.observeForever(this);
        }

        void unplug() {
            mLiveData.removeObserver(this);
        }

        @Override
        public void onChanged(@Nullable V v) {
            if (mVersion != mLiveData.getVersion()) {
                mVersion = mLiveData.getVersion();
                mObserver.onChanged(v);
            }
        }
    }
複製代碼

首先Source是一個觀察者,能夠看到,咱們外部使用的Observer會以Source的成員變量的形式,添加到傳入的LiveData中。值得注意的是,這裏使用了mLiveData.observeForever(this);

observeForever()用法能夠看到,咱們並無傳遞LifecycleOwner,所以它並不具有生命感知能力。從註釋中也可見一斑:This means that the given observer will receive all events and will never be automatically removed.

map()的原理就是基於MediatorLiveData,MediatorLiveData內部會將傳遞進來的LiveData和Observer封裝成內部類,而後放在內部維護的一個Map中。而且自動幫咱們完成observeForever()和removeObserver()

5.總結

  • LiveData基於觀察者模式實現,而且和LifecycleOwner進行綁定,而LifecycleOwner又被Fragment和Activity實現,因此它能夠感知生命週期;在當前的LifecycleOwner不處於活動狀態(例如onPasue()onStop())時,LiveData是不會回調observe()的,由於沒有意義.
  • 同時LiveData只會在LifecycleOwner處於Active的狀態下通知數據改變,果數據改變發生在非 active 狀態,數據會變化,可是不發送通知,等 owner 回到 active 的狀態下,再發送通知;
  • LiveData在DESTROYED時會移除Observer,取消訂閱,不會出現內存泄漏
  • postValue在異步線程,setValue在主線程
  • 若是LiveData沒有被observe(),那麼此時你調用這個LiveData的postValue(...)/value=...,是沒有任何做用

固然官方推薦咱們LiveData配合ViewModel一塊兒使用,由於LiveData通常都出如今ViewModel中,因此咱們下篇文章會繼續分析ViewModel.

相關文章
相關標籤/搜索