成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

【AAC 系列三】深入理解架構(gòu)組件:LiveData

番茄西紅柿 / 3486人閱讀

摘要:前言本文是深入理解系列文章第三篇源碼基于系列前兩篇在之前我們深入研究了的實(shí)現(xiàn)原理,并在文末提到了以及,這次我們來講講。此時(shí)的流程是可以稱之為生命周期改變觸發(fā)的流程,另外還有一種流程是觸發(fā)的流程,共兩種。

0. 前言

本文是深入理解「Android Architecture Components」系列文章第三篇 源碼基于 android.arch.lifecycle:livedata-core:1.1.1

系列前兩篇: juejin.im/post/5cd4ea… juejin.im/post/5cd816…

在之前我們深入研究了 Lifecycle 的實(shí)現(xiàn)原理,并在文末提到了LiveData 以及 ViewModel,這次我們來講講 LiveData。

LiveData 是 Android Architecture Components 中的一員,先看下官方是如何介紹的:

LiveData is an observable data holder class. Unlike a regular observable, LiveData is lifecycle-aware, meaning it respects the lifecycle of other app components, such as activities, fragments, or services. This awareness ensures LiveData only updates app component observers that are in an active lifecycle state. [見 9.1]

This class is designed to hold individual data fields of ViewModel, but can also be used for sharing data between different modules in your application in a decoupled fashion. [見 9.2]

簡(jiǎn)單講 LiveData 是一個(gè)能夠感知生命周期、可觀察的數(shù)據(jù)持有類 ,它被設(shè)計(jì)成 ViewModel 的一個(gè)成員變量;可以以一個(gè) 更解耦 的方式來共享數(shù)據(jù)

實(shí)際使用下來發(fā)現(xiàn) LiveData 有幾個(gè)特性

    LiveData 的實(shí)現(xiàn)基于觀察者模式;

    LiveData 跟 LifecycleOwner 綁定,能感知生命周期變化,并且只會(huì)在 LifecycleOwner 處于 Active 狀態(tài)(STARTED/RESUMED)下通知數(shù)據(jù)改變;

    LiveData 會(huì)自動(dòng)在 DESTROYED 的狀態(tài)下移除 Observer ,取消訂閱,所以不用擔(dān)心內(nèi)存泄露;

那么 LiveData 上述特性的原理是怎么樣的呢?
使用 LiveData 又需要注意些什么呢?

本文將圍繞此展開。

1. LiveData 的基本使用

雖然 LiveData 通常跟 ViewModel 配合使用,不過也可以多帶帶使用,為了簡(jiǎn)單起見,這里不配合 ViewModel。

以下是一個(gè)簡(jiǎn)單的例子:

MutableLiveData liveString = new MutableLiveData<>();
liveString.observe(this, new Observer() {
  @Override
  public void onChanged(@Nullable final String s) {
    Log.d(TAG, "onChanged() called with: s = [" + s + "]");
  }
});

liveString.postValue("程序亦非猿");

運(yùn)行后可以看到日志輸出:onChanged() called with: s = [程序亦非猿] 。

釋義:
定義一個(gè) MutableLiveData (LiveData 的一個(gè)常用子類),通過 observe 方法可以訂閱修改數(shù)據(jù)的通知,通過 postValue()  或者 setValue()  方法可以更新數(shù)據(jù),已經(jīng)訂閱的 Observer 能夠得到數(shù)據(jù)更改的通知,也即回調(diào) onChanged() 方法。

這樣就算是用上 LiveData 了。

接下來,上干貨!

2. LiveData 的原理分析

在分析原理前,再明確一下我們的疑問:

    LiveData 是如何跟 LifecycleOwner 進(jìn)行綁定,做到感知生命周期的?

    LiveData 只在 LifecycleOwner active 狀態(tài)發(fā)送通知,是怎么處理的?

    LiveData 會(huì)自動(dòng)在 DESTROY 的狀態(tài)下取消訂閱,是怎么處理的?

    通過 setValue()/postValue() 更新數(shù)據(jù)的處理流程是如何?

    生命周期變化后數(shù)據(jù)處理流程是怎么樣的?

同時(shí)提前看下我整理的 LiveData UML 圖,對(duì) LiveData 有個(gè)整體的了解,后續(xù)的涉及到的類都在這里了,有助于理解。


(圖1.LiveData 類圖)

OK, here we go!

2.1 LiveData.observe()

LiveData 的使用流程從 observe() 開始,咱們嘗試從 observe() 方法 開始分析:

    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
        //如果是 DESTROYED 的狀態(tài)則忽略
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        //把 Observer 用 LifecycleBoundObserver 包裝起來
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        //緩存起來
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        //如果已經(jīng) observe 過 并且兩次的 owner 不同則報(bào)錯(cuò)
        if (existing != null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        //綁定 owner
        owner.getLifecycle().addObserver(wrapper);
    }

可以看到 observe 方法里把我們傳遞的 observer 用 LifecycleBoundObserver  包裝了起來,并且存入了 mObservers  ,并且跟 owner 進(jìn)行了關(guān)聯(lián)。

并且做了兩個(gè)特殊處理:

    忽視處于 DESTROYED 的 owner 的注冊(cè)行為

    將一個(gè) Observer 同時(shí)綁定兩個(gè) owner 的行為視為非法操作,也即一個(gè) Observer 只能綁定一個(gè) owner,而 owner 可以有多個(gè) Observer;

這里出現(xiàn)了幾個(gè)新的類 LifecycleBoundObserverObserverWrapper 來看看。

2.2 LifecycleBoundObserver

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

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

        @Override
        boolean shouldBeActive() {
            // 判斷 owner 當(dāng)前的狀態(tài)是否是至少 STARTED
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            //生命周期改變,如果是 DESTROYED 就自動(dòng)解除
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
            //ObserverWrapper.activeStateChanged
            activeStateChanged(shouldBeActive());
        }

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

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

**ObserverWrapper **:

    private abstract class ObserverWrapper {
        final Observer mObserver;
        boolean mActive;
        int mLastVersion = START_VERSION;

        ObserverWrapper(Observer observer) {
            mObserver = observer;
        }
				//是否是 active 狀態(tài)
        abstract boolean shouldBeActive();

        boolean isAttachedTo(LifecycleOwner owner) {
            return false;
        }

        void detachObserver() {
        }

        void activeStateChanged(boolean newActive) {
            if (newActive == mActive) {
                return;
            }
            // immediately set active state, so wed 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();
            }
            //如果 active 狀態(tài)下,則發(fā)送數(shù)據(jù)更新通知
            if (mActive) {
                dispatchingValue(this);
            }
        }
    }

仔細(xì)看下這兩個(gè)類其實(shí)就能解答疑問了。

LifecycleBoundObserver 是 抽象類 ObserverWrapper 的子類,重寫了 shouldBeActive() 方法,在 owner 處于至少是 STARTED 的狀態(tài)下認(rèn)為是 active 狀態(tài);并且它也實(shí)現(xiàn)了 GenericLifecycleObserver 接口,可以監(jiān)聽 lifecycle 回調(diào),并且在 onStateChanged() 方法里處理了生命周期改變的事件,當(dāng)接收到 DESTROYED 的事件會(huì)自動(dòng)解除跟 owner 的綁定,并且將下個(gè)流程交給了 activeStateChanged() 。

到這里 【2.1】、【2.3】的問題已經(jīng)有了答案:

【2.1】答:LifeData 在 observe 方法中用 LifecycleBoundObserver 包裝了 observer ,并且通過它綁定了owner。
【2.3】答:LifecycleBoundObserver 在 onStateChanged() 方法里處理了生命周期改變的事件,當(dāng)接收到 DESTROYED 的事件會(huì)自動(dòng)解除跟 owner 的綁定。

這里需要注意的是,當(dāng)我們調(diào)用 observe() 注冊(cè)后,由于綁定了 owner,所以在 active 的情況下,LiveData 如果有數(shù)據(jù),則 Observer 會(huì)立馬接受到該數(shù)據(jù)修改的通知。

此時(shí)的流程是:

observe-->
  onStateChanged-->
    activeStateChanged-->
     dispatchingValue-->
       considerNotify-->
          onChanged

可以稱之為生命周期改變觸發(fā)的流程,另外還有一種流程是 postValue&setValue 觸發(fā)的流程,共兩種。

2.3 activeStateChanged(boolean)

在 activeStateChanged() 方法里,處理了 onActive() 跟 onInactive() 回調(diào)的相關(guān)邏輯處理,并且調(diào)用了dispatchingValue(this) 。(MediatorLiveData 用到了 onActive() 跟 onInactive() 有興趣自行了解,這里不展開)

接下去探索 dispatchingValue

2.4 dispatchingValue(ObserverWrapper) 分析

    private void dispatchingValue(@Nullable ObserverWrapper initiator) {
        //如果正在分發(fā)則直接返回
        if (mDispatchingValue) {
            //標(biāo)記分發(fā)失效
            mDispatchInvalidated = true;
            return;
        }
        //標(biāo)記分發(fā)開始
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            //生命周期改變調(diào)用的方法 initiator 不為 null
            if (initiator != null) {
                considerNotify(initiator);
                initiator = null;
            } else {
                //postValue/setValue 方法調(diào)用 傳遞的 initiator 為 null
                for (Iterator, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        //標(biāo)記分發(fā)結(jié)束
        mDispatchingValue = false;
    }

considerNotify(ObserverWrapper)  方法:

    private void considerNotify(ObserverWrapper observer) {
        //檢查狀態(tài) 確保不會(huì)分發(fā)給 inactive 的 observer
        if (!observer.mActive) {
            return;
        }
        // Check latest state b4 dispatch. Maybe it changed state but we didnt 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 weve not received that event, we better not
        // notify for a more predictable notification order.
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        //setValue 會(huì)增加 version ,初始 version 為-1
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        //noinspection unchecked
        observer.mObserver.onChanged((T) mData);
    }

可以看到 dispatchingValue 正是分發(fā)事件邏輯的處理方法,而 considerNotify 方法則確保了只將最新的數(shù)據(jù)分發(fā)給 active 狀態(tài)下的 Observer 。

另外也可以看到 LiveData 引入了版本管理來管理數(shù)據(jù) (mData)以確保發(fā)送的數(shù)據(jù)總是最新的。(具體不多講)

dispatchingValue 這里分兩種情況:

    ObserverWrapper 不為 null

    ObserverWrapper 為 null

需要著重講一下。

2.4.1 ObserverWrapper 不為 null 的情況

上面提到過,LifecycleBoundObserver.onStateChanged 方法里調(diào)用了 activeStateChanged ,而該方法調(diào)用dispatchingValue(this);傳入了 this ,也就是 LifecycleBoundObserver ,這時(shí)候不為 null 。

也就是說生命周期改變觸發(fā)的流程就是這種情況,這種情況下,只會(huì)通知跟該 Owner 綁定的 Observer。

2.4.2 ObserverWrapper 為 null 的情況

上面我也提前說了,除了生命周期改變觸發(fā)的流程外,還有 postValue&setValue 流程,來看下這倆方法。

private final Runnable mPostValueRunnable = new Runnable() {
    @Override
    public void run() {
        Object newValue;
        synchronized (mDataLock) {
            newValue = mPendingData;
            mPendingData = NOT_SET;
        }
        //noinspection unchecked
        //調(diào)用 setValue
        setValue((T) newValue);
    }
};

protected void postValue(T value) {
    boolean postTask;
    synchronized (mDataLock) {
        postTask = mPendingData == NOT_SET;
        mPendingData = value;
    }
    if (!postTask) {
        return;
    }
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}

@MainThread
protected void setValue(T value) {
    //必須在主線程調(diào)用 否則會(huì) crash
    assertMainThread("setValue");
    mVersion++;//增加版本號(hào)
    mData = value;
    //傳入了 null
    dispatchingValue(null);
}

LiveData 的 postValue 方法其實(shí)就是把操作 post 到主線程,最后調(diào)用的還是 setValue 方法,注意 setValue 必須是在主線程調(diào)用。

并且可以看到** setValue 方法調(diào)用了 dispatchingValue 方法,并傳入了 null ,這個(gè)時(shí)候的流程則會(huì)通知 active 的mObservers**。

到這里之前的剩下的所有疑問也都可以解答了。

LiveData 的兩個(gè)流程都會(huì)走到 dispatchingValue 處理分發(fā)通知邏輯,并且在分發(fā)通知前會(huì)判斷 owner 的狀態(tài),再加上 LiveData 本身內(nèi)部的版本管理,確保了只會(huì)發(fā)送最新的數(shù)據(jù)給 active 狀態(tài)下的 Observer。

**注意:**LiveData 對(duì)同時(shí)多次修改數(shù)據(jù)做了處理,如果同時(shí)多次修改,只會(huì)修改為最新的數(shù)據(jù)。

3. 圖解 LiveData

3.1 LiveData 類圖

再看一遍類圖,回顧一下:


(圖2.LiveData 類圖)

3.2 LiveData 流程圖

Lifecycle 改變觸發(fā)流程:


(圖3.Lifecycle 改變觸發(fā)流程圖)

Lifecycle postValue/setValue 觸發(fā)流程:


(圖4.setValue 改變觸發(fā)流程圖)

4. LiveData tips and recipes


LiveData 還有很多其他相關(guān)知識(shí),這里列舉一些,更多實(shí)踐可以看一下【7.6】。

4.1 Sticky Event

LiveData 被訂閱時(shí),如果之前已經(jīng)更改過數(shù)據(jù),并且當(dāng)前 owner 為 active 的狀態(tài),activeStateChanged() 會(huì)被調(diào)用,也即會(huì)立馬通知到 Observer ,這樣其實(shí)就類似 EventBus 的 sticky event 的功能,需要注意的是,很多時(shí)候我們并不需要該功能。具體可以看一下【7.6】的處理。

4.2 AlwaysActiveObserver

默認(rèn)情況下,LiveData 會(huì)跟 LicycleOwner 綁定,只在 active 狀態(tài)下更新,如若想要不管在什么狀態(tài)下都能接收到數(shù)據(jù)的更改通知的話,怎么辦?這時(shí)候需要使用 AlwaysActiveObserver ,改調(diào)用 observe 方法為調(diào)用 LiveData.observeForever(Observer) 方法即可。

4.3 MediatorLiveData

LiveData 還有一個(gè)子類是 MediatorLiveData,它允許我們合并多個(gè) LiveData,任何一個(gè) LiveData 有更新就會(huì)發(fā)送通知。比如我們的數(shù)據(jù)來源有兩個(gè),一個(gè)數(shù)據(jù)庫(kù)一個(gè)網(wǎng)絡(luò),這時(shí)候我們會(huì)有兩個(gè) DataSource,也就是兩個(gè) LiveData,這個(gè)時(shí)候我們可以使用 MediatorLiveData 來 merge 這兩個(gè) LiveData。

4.4 Transformations

Transformations 允許我們把一個(gè) LiveData 進(jìn)行處理,變化成另外一個(gè) LiveData,目前支持 map 跟 switchMap 兩個(gè)方法,跟 RxJava 的操作類似。

比如,用 map 把一個(gè) String 類型的 LiveData 轉(zhuǎn)換成 Integer 類型:

Transformations.map(liveString, new Function() {
  @Override
  public Integer apply(final String input) {
    return Integer.valueOf(input);
  }
}).observe(this, new Observer() {
  @Override
  public void onChanged(@Nullable final Integer integer) {

  }
});

4.4 LiveDataBus

EventBus 基于觀察者模式,LiveData 也是,所以 LiveData 可以被用來做成 LiveDataBus,有興趣可以搜索。

5. 知識(shí)點(diǎn)匯總

    LiveData 的實(shí)現(xiàn)基于觀察者模式(reactive patterns);

    LiveData 跟 LifecycleOwner 綁定,能感知生命周期變化,并且只會(huì)在 LifecycleOwner 處于 Active 狀態(tài)(STARTED/RESUMED)下通知數(shù)據(jù)改變;如果數(shù)據(jù)改變發(fā)生在非 active 狀態(tài),數(shù)據(jù)會(huì)變化,但是不發(fā)送通知,等 owner 回到 active 的狀態(tài)下,再發(fā)送通知;

    如果想要一直收到通知,則需要用 observeForever() 方法;

    LiveData 會(huì)自動(dòng)在 DESTROYED 的狀態(tài)下移除 Observer ,取消訂閱,所以不用擔(dān)心內(nèi)存泄露;

    在 LifecycleOwner 處于 DESTROYED 的狀態(tài)下,不能訂閱;

    postValue 方法其實(shí)最后調(diào)用了 setValue 只不過把操作放到主線程,適合在異步線程里調(diào)用,setValue 必須在主線程里調(diào)用;

    如果同時(shí)多次調(diào)用 postValue 或 setValue 修改數(shù)據(jù),只會(huì)修改成最新的那個(gè)數(shù)據(jù),也即只會(huì)收到一次通知(set post混合調(diào)用則不一定);

    如果 LiveData 有數(shù)據(jù),并且 owner 在 active 狀態(tài)下,那么在訂閱的時(shí)候,會(huì)立馬收到一次通知;

    一個(gè) Observer 實(shí)例,只能綁定一個(gè) LifecycleOwner,而一個(gè) owner 可以綁定多個(gè) Observer 實(shí)例;

    LiveData 利用版本管理、綁定 Lifecycle 確保了只會(huì)發(fā)送最新的數(shù)據(jù)給 active 狀態(tài)下的 Observer;

6. 總結(jié)

LiveData 基于觀察者模式,并且可以感知生命周期,這使得我們使用 LiveData 既可以享受觀察者模式帶來的隔離數(shù)據(jù)與 UI 等強(qiáng)大的解耦能力,還可以享受感知生命周期帶來的巨大便利。并且還無需擔(dān)心內(nèi)存泄露這個(gè)令人頭疼的問題。

我們可以使用 LiveData 非常輕松地做到一些非常高效的操作,如僅在 active 的狀態(tài)下刷新 UI,可以避免不必要的數(shù)據(jù)刷新。

顯而易見 LiveData 本身的優(yōu)秀特性有著巨大的價(jià)值,利用好絕對(duì)是架構(gòu)設(shè)計(jì)中的一大利器,另外 LiveData 配合 ViewModel 可以發(fā)揮更大的價(jià)值,機(jī)智的你一定已經(jīng)知道下一篇文章講什么了。

7. 參考與推薦

    LiveData Overview : developer.android.com/topic/libra…

    LiveData doc : developer.android.com/reference/a…

    developer.android.com/reference/a…

    developer.android.com/reference/a…

    github.com/googlesampl…

    github.com/googlesampl…

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/7061.html

相關(guān)文章

  • 如何開發(fā)一款以太坊安卓錢包系列3 - 資產(chǎn)信息展示

    摘要:這是如何開發(fā)以太坊安卓錢包系列第篇,錢包賬號(hào)資產(chǎn)信息展示,展示信息主要包括賬號(hào)地址余額及該賬號(hào)所擁有的及余額。 本文首發(fā)于深入淺出區(qū)塊鏈社區(qū)原文鏈接:開發(fā)以太坊安卓錢包系列第3篇,原文已更新,請(qǐng)讀者前往原文閱讀 請(qǐng)大家前往深入淺出區(qū)塊鏈主站, 獲取最新內(nèi)容。 這是如何開發(fā)以太坊(安卓)錢包系列第3篇, 錢包賬號(hào)資產(chǎn)信息展示,展示信息主要包括賬號(hào)地址、eth余額及該賬號(hào)所擁有的Token...

    asce1885 評(píng)論0 收藏0
  • 如何開發(fā)一款以太坊安卓錢包系列3 - 資產(chǎn)信息展示

    摘要:這是如何開發(fā)以太坊安卓錢包系列第篇,錢包賬號(hào)資產(chǎn)信息展示,展示信息主要包括賬號(hào)地址余額及該賬號(hào)所擁有的及余額。 本文首發(fā)于深入淺出區(qū)塊鏈社區(qū)原文鏈接:開發(fā)以太坊安卓錢包系列第3篇,原文已更新,請(qǐng)讀者前往原文閱讀 請(qǐng)大家前往深入淺出區(qū)塊鏈主站, 獲取最新內(nèi)容。 這是如何開發(fā)以太坊(安卓)錢包系列第3篇, 錢包賬號(hào)資產(chǎn)信息展示,展示信息主要包括賬號(hào)地址、eth余額及該賬號(hào)所擁有的Token...

    taohonghui 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<