Android Jetpack架構(gòu)組件之LiveData

???????

有時(shí)候,靠單純的判斷并不能確定成功的幾率秆吵。與其在等待中浪費(fèi)青春,不如在追求中燃燒生命五慈∧杉牛——《狼道》

目錄
前言
一、簡介
二泻拦、基本使用
三毙芜、源碼分析
四、內(nèi)容推薦
五争拐、項(xiàng)目參考

前言

——這篇記錄的是一個(gè)常用的Jetpack架構(gòu)組件之一的LiveData腋粥。通俗講它有兩個(gè)顯著作用:1.通過觀察者模式當(dāng)數(shù)據(jù)發(fā)生變化的時(shí)候通知UI更新。2.與生命周期綁定在一起架曹,當(dāng)組件生命周期發(fā)生變化處于激活時(shí)通知UI更新隘冲。這么說可能還有點(diǎn)不清晰,具體請看下文分解:

一绑雄、簡介

官網(wǎng)文檔 / Jetpack組件

(1)是什么

——LiveData是一個(gè)可觀察的數(shù)據(jù)持有者類展辞。與常規(guī)的可觀察對象不同,LiveData是生命周期感知的万牺,這意味著它尊重其他應(yīng)用程序組件(如活動(dòng)罗珍、片段或服務(wù))的生命周期洽腺。這種意識確保LiveData只更新處于活動(dòng)生命周期狀態(tài)的應(yīng)用程序組件觀察者。

(2)有什么用

  1. 數(shù)據(jù)可以被觀察者訂閱

  2. 能夠感知組件(Fragment覆旱、Activity蘸朋、Service)的生命周期

  3. 只有在組件出于激活狀態(tài)(STARTED、RESUMED)才會通知觀察者有數(shù)據(jù)更新

(3)有什么優(yōu)點(diǎn)

  1. 能夠保證數(shù)據(jù)和UI統(tǒng)一

  2. 減少內(nèi)存泄漏

  3. 當(dāng)Activity停止時(shí)不會引起崩潰

  4. 不需要額外的手動(dòng)處理來響應(yīng)生命周期的變化

  5. 組件和數(shù)據(jù)相關(guān)的內(nèi)容能實(shí)時(shí)更新

  6. 針對configuration change時(shí)扣唱,不需要額外的處理來保存數(shù)據(jù)

  7. 資源共享

?二藕坯、基本使用

(4)怎么使用

LiveData的使用方式有兩種:1.使用LiveData對象;2.繼承LiveData類

  • 使用LiveData對象

實(shí)現(xiàn)步驟:

1.創(chuàng)建一個(gè)LiveData實(shí)例來保存數(shù)據(jù)

2.創(chuàng)建Observer監(jiān)聽數(shù)據(jù)改變

3.設(shè)置值,如果有活動(dòng)的觀察者,值將被發(fā)送給他們

//創(chuàng)建一個(gè)定義onChanged()方法的觀察者對象,該方法控制LiveData對象持有的數(shù)據(jù)更改時(shí)發(fā)生的情況画舌。
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 1.創(chuàng)建一個(gè)LiveData實(shí)例來保存數(shù)據(jù)
        MutableLiveData<String> currentName = new MutableLiveData<String>();
        // 2.創(chuàng)建Observer監(jiān)聽數(shù)據(jù)改變
        final Observer<String> nameObserver = new Observer<String>() {
            @Override
            public void onChanged(@Nullable final String newName) {
                //更新UI操作
                nameTextView.setText(newName);
            }
        };
        // 添加Observer
        currentName.observe(this, nameObserver);

    }

    public void onClick(View view){
        // 3.設(shè)置值 如果有活動(dòng)的觀察者 值將被發(fā)送給他們
        //主線程使用setValue
        model.getCurrentName().setValue("xxxx")
        //后臺線程使用postValue
        //model.getCurrentName().postValue("xxxx")
    }
}
  • 繼承LiveData類
//Demo1擴(kuò)展LiveData類(監(jiān)聽網(wǎng)絡(luò)狀態(tài))
public class NetworkLiveData extends LiveData<NetworkInfo> {

    private final Context mContext;
    static NetworkLiveData mNetworkLiveData;
    private NetworkReceiver mNetworkReceiver;
    private final IntentFilter mIntentFilter;

    private static final String TAG = "NetworkLiveData";

    public NetworkLiveData(Context context) {
        mContext = context.getApplicationContext();
        mNetworkReceiver = new NetworkReceiver();
        mIntentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
    }
    //單例
    public static NetworkLiveData getInstance(Context context) {
        if (mNetworkLiveData == null) {
            mNetworkLiveData = new NetworkLiveData(context);
        }
        return mNetworkLiveData;
    }

    @Override
    protected void onActive() {
        super.onActive();
        //當(dāng)組件處于激活狀態(tài)時(shí)注冊廣播
        mContext.registerReceiver(mNetworkReceiver, mIntentFilter);
    }

    @Override
    protected void onInactive() {
        super.onInactive();
         //當(dāng)組件處于銷毀狀態(tài)時(shí)注銷廣播
        mContext.unregisterReceiver(mNetworkReceiver);
    }
    //監(jiān)聽網(wǎng)絡(luò)狀態(tài)
    private static class NetworkReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            ConnectivityManager manager = (ConnectivityManager) context
                    .getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo activeNetwork = manager.getActiveNetworkInfo();
            getInstance(context).setValue(activeNetwork);
        }
    }
}

//使用過程
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        NetworkLiveData.getInstance(this).observe(this,new Observer(){
            @Override
            public void onChanged(@Nullable final String newName) {
                // Update UI
            }
        })
    }
}

LiveData的使用方式相對比較簡單堕担。實(shí)現(xiàn)方式也比較容易。就不描述太多細(xì)節(jié)曲聂。相信大家看代碼會比看解釋更容易理解霹购。

三、源碼分析

——因?yàn)長iveData是抽象類朋腋,所以我們要使用它就需要寫一個(gè)類來繼承LiveData齐疙。
——當(dāng)然系統(tǒng)也幫我們寫了幾個(gè)可直接使用的類,MutableLiveData,MediatorLiveData旭咽。

1.MutableLiveData源碼

// 創(chuàng)建了一個(gè)MutableLiveData實(shí)例
MutableLiveData<String> liveData = new MutableLiveData<>();
// MutableLiveData源碼
public class MutableLiveData<T> extends LiveData<T> {
      @Override
      public void postValue(T value) {
         super.postValue(value);
      }
      @Override
      public void setValue(T value) {
            super.setValue(value);
      }
}

——MutableLiveData把LiveData的postValue方法與setValue接口暴露出來可供調(diào)用贞奋。這個(gè)后面使用的時(shí)候在分析

2.LiveData的observe源碼

//創(chuàng)建Observer監(jiān)聽數(shù)據(jù)改變
liveData.observe(this, new Observer<String>() {
    @Override
    public void onChanged(String s) {
        binding.setName(s);
    }
});

(1)observe源碼

        //該方法主要把observer與Activity(組件)的生命周期綁定在一起。當(dāng)Activity(組件)狀態(tài)改變的時(shí)候通知observer
    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        //請看(5) 
        assertMainThread("observe");
        //當(dāng)前Activity(組件)狀態(tài)處于銷毀狀態(tài)時(shí) 是則返回 
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        //請看(2) 
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        //以鍵值對的形式存儲observer于LifecycleBoundObserver穷绵,如果LifecycleBoundObserver已經(jīng)存儲過則ObserverWrapper返回空 
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        //判斷是否是同一個(gè)LifecycleOwner 
        if (existing != null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        //這里攔截已經(jīng)添加過的LifecycleBoundObserver
        if (existing != null) {
            return;
        }
        //添加一個(gè)wrapper轿塔,它將在LifecycleOwner狀態(tài)更改時(shí)得到通知 具體原理可以看樓主Lifecycle原理篇
        owner.getLifecycle().addObserver(wrapper);
    }

(2)LiveData的內(nèi)部類LifecycleBoundObserver源碼

        //該類通過實(shí)現(xiàn)GenericLifecycleObserver監(jiān)聽生命周期變化更新Observer傳遞的數(shù)據(jù)
    //繼承ObserverWrapper根據(jù)Activity(組件)的生命周期管理著Observer
    class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
        @NonNull
        final LifecycleOwner mOwner;
        //observer傳給ObserverWrapper的構(gòu)造函數(shù)
        LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
            super(observer);
            mOwner = owner;
        }
        //返回當(dāng)前Activity(組件)的生命狀態(tài)是否是STARTED或者RESUMED
        @Override
        boolean shouldBeActive() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }
        //通過實(shí)現(xiàn)GenericLifecycleObserver接口的onStateChanged方法監(jiān)聽Activity(組件)生命周期變化
        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            //判斷Activity(組件)生命周期狀態(tài)是否是DESTROYED  是則移除觀察者
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                //請看(4)
                removeObserver(mObserver);
                return;
            }
            //Activity(組件)生命周期改變 通知ObserverWrapper
            activeStateChanged(shouldBeActive());
        }
        //重寫ObserverWrapper的isAttachedTo方法判斷是不是同一個(gè)生命周期
        @Override
        boolean isAttachedTo(LifecycleOwner owner) {
            return mOwner == owner;
        }
        //重寫ObserverWrapper的detachObserver方法移除LifecycleBoundObserver
        @Override
        void detachObserver() {
            mOwner.getLifecycle().removeObserver(this);
        }
    }

(3)LiveData的內(nèi)部抽象類ObserverWrapper源碼

        // 封裝Observer的一些屬性與方法
    private abstract class ObserverWrapper {
        final Observer<? super T> mObserver;
        boolean mActive;
        int mLastVersion = START_VERSION;
        ObserverWrapper(Observer<? super T> observer) {
            mObserver = observer;
        }
        abstract boolean shouldBeActive();
        //判斷是否是同一個(gè)生命周期
        boolean isAttachedTo(LifecycleOwner owner) {
            return false;
        }
        void detachObserver() {}        
        // 設(shè)置ObserverWrapper的mActive狀態(tài)與添加mActiveCount數(shù)量 
        void activeStateChanged(boolean newActive) {
            //判斷Activity(組件)狀態(tài)是否改變 有沒則返回
            if (newActive == mActive) {
                return;
            }
            //設(shè)置mActive狀態(tài)
            mActive = newActive;
            //判斷當(dāng)前觀察者數(shù)量是否為0
            boolean wasInactive = LiveData.this.mActiveCount == 0;
            //當(dāng)Activity(組件)是激活狀態(tài)時(shí)+1 反之-1
            LiveData.this.mActiveCount += mActive ? 1 : -1;
            //當(dāng)Activity(組件)狀態(tài)屬于激活并wasInactive為ture時(shí)調(diào)用onActive() 
            if (wasInactive && mActive) {
                //也就是當(dāng)觀察者的數(shù)量從0變?yōu)?時(shí)調(diào)用
                onActive();
            }
            //當(dāng)活動(dòng)觀察者的數(shù)量從1變?yōu)?時(shí)調(diào)用
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                onInactive();
            }
            // 當(dāng)Activity(組件)屬于激活是調(diào)用dispatchingValue
            if (mActive) {
                //查看(6)分析
                dispatchingValue(this);
            }
        }
    }

(4)LiveData類的removeObserver方法

        //從觀察者列表中刪除給定的觀察者
    @MainThread
    public void removeObserver(@NonNull final Observer<? super T> observer) {
        //請看(5) 
        assertMainThread("removeObserver");
        //從mObservers列表中移除observer
        ObserverWrapper removed = mObservers.remove(observer);
        if (removed == null) {
            return;
        }
        //移除Observer并通知相關(guān)屬性記錄更改
        removed.detachObserver();
        removed.activeStateChanged(false);
    }

(5)LiveData類的assertMainThread方法

        //用于判斷是否在主線程  不是則拋出異常IllegalStateException
    private static void assertMainThread(String methodName) {
        if (!ArchTaskExecutor.getInstance().isMainThread()) {
            throw new IllegalStateException("Cannot invoke " + methodName + " on a background"
                    + " thread");
        }
    }

(6)LiveData類的dispatchingValue方法分析

        // 經(jīng)過一系列的判斷 最后調(diào)用considerNotify方法更新數(shù)據(jù)
    @SuppressWarnings("WeakerAccess") /* synthetic access */
    void dispatchingValue(@Nullable ObserverWrapper initiator) {
        //判斷值是否在分發(fā)當(dāng)中    
            if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            if (initiator != null) {
                //請看(7) 
                considerNotify(initiator);
                initiator = null;
            } else {
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    //請看(7) 
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
            mDispatchingValue = false;
        }
        }

(7)LiveData類的considerNotify方法分析

        //當(dāng)Activity(組件)屬于激活狀態(tài)時(shí) 把數(shù)據(jù)傳給observer的onChanged方法
    private void considerNotify(ObserverWrapper observer) {
        // Activity(組件)狀態(tài)屬于非激活狀態(tài)時(shí) 返回
        if (!observer.mActive) {
            return;
        }
        // 繼續(xù)檢測observer屬于非激活狀態(tài)時(shí)設(shè)置activeStateChanged為false 并返回
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        // 用于攔截?cái)?shù)據(jù)沒更新,當(dāng)調(diào)用setValue時(shí)mVersion會加1,也就是沒有新數(shù)據(jù)時(shí)在這里會被攔截 不會調(diào)用到mObserver.onChanged方法
        if (observer.mLastVersion > = mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        //把數(shù)據(jù)傳給observer的onChanged方法
        observer.mObserver.onChanged((T) mData);
    }

總結(jié):

  • 通過liveData.observe()方法首先判斷組件若處于激活狀態(tài),創(chuàng)建綁定生命周期與觀察者的關(guān)鍵類仲墨。

  • 判斷該類是否存儲過勾缭,若存儲過則拋出異常。

  • 將綁定類添加到lifecycle生命周期中目养,監(jiān)聽組件生命周期變化俩由。(具體實(shí)現(xiàn)方式看Lifecycle原理)

  • 當(dāng)生命周期發(fā)生變化時(shí)調(diào)用觀察者的onChange()方法 ,把值傳遞過去癌蚁。中間經(jīng)過一系列判斷幻梯,具體看源碼。

3.設(shè)置值setValue源碼

        //通過解析1的MutableLiveData源碼可知最后調(diào)用的是LiveData的setValue與postValue
    //設(shè)置值努释。如果有活動(dòng)的觀察者碘梢,值將被發(fā)送給他們
    @MainThread
    protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        //請看(6)
        dispatchingValue(null);
    }
    //非主線程設(shè)置值
    protected void postValue(T value) {
        boolean postTask;
        //同步代碼塊 
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        //檢測上一個(gè)任務(wù)是否執(zhí)行完畢
        if (!postTask) {
            return;
        }
        //將任務(wù)發(fā)送到主線程以設(shè)置給定的值
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }   

    private final Runnable mPostValueRunnable = new Runnable() {
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            //最后也是通過setValue方法進(jìn)行通知
            setValue((T) newValue);
        }
    };

總結(jié):

  • postValue方法主要是將任務(wù)切換到主線程并調(diào)用了setValue方通知觀察者。
  • 而setValue方法則是調(diào)用了dispatchingValue()將值分發(fā)給Observer.onChanged方法伐蒂。

四痘系、內(nèi)容推薦

五、項(xiàng)目參考

本文相關(guān)代碼及Demo都放在下面項(xiàng)目中饿自。有興趣可體驗(yàn)一把

Github / apk下載體驗(yàn)地址

若您發(fā)現(xiàn)文章中存在錯(cuò)誤或不足的地方汰翠,希望您能指出龄坪!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市复唤,隨后出現(xiàn)的幾起案子健田,更是在濱河造成了極大的恐慌,老刑警劉巖佛纫,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件妓局,死亡現(xiàn)場離奇詭異,居然都是意外死亡呈宇,警方通過查閱死者的電腦和手機(jī)好爬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來甥啄,“玉大人存炮,你說我怎么就攤上這事◎诶欤” “怎么了穆桂?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長融虽。 經(jīng)常有香客問我享完,道長,這世上最難降的妖魔是什么有额? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任般又,我火速辦了婚禮,結(jié)果婚禮上巍佑,老公的妹妹穿的比我還像新娘茴迁。我一直安慰自己,他們只是感情好句狼,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布笋熬。 她就那樣靜靜地躺著热某,像睡著了一般腻菇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上昔馋,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天筹吐,我揣著相機(jī)與錄音,去河邊找鬼秘遏。 笑死丘薛,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的邦危。 我是一名探鬼主播洋侨,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼舍扰,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了希坚?” 一聲冷哼從身側(cè)響起边苹,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎裁僧,沒想到半個(gè)月后个束,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡聊疲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年茬底,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片获洲。...
    茶點(diǎn)故事閱讀 40,102評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡阱表,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出昌妹,到底是詐尸還是另有隱情捶枢,我是刑警寧澤,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布飞崖,位于F島的核電站烂叔,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏固歪。R本人自食惡果不足惜蒜鸡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望牢裳。 院中可真熱鬧逢防,春花似錦、人聲如沸蒲讯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽判帮。三九已至局嘁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間晦墙,已是汗流浹背悦昵。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留晌畅,地道東北人但指。 一個(gè)月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親棋凳。 傳聞我的和親對象是個(gè)殘疾皇子拦坠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android Jetpack介紹 Android Jetpack 是一套組件、工具和指導(dǎo)剩岳,可以幫助您快速構(gòu)建出色...
    jiantaocd閱讀 23,957評論 6 54
  • 最是人間留不住尤蒿,朱顏辭鏡花辭樹——王維 最是人間留不住腰池,朱顏辭鏡花辭樹——王維 曾經(jīng)有一個(gè)人對我說:別對我抱太大希...
    碧海飛鴻2016閱讀 209評論 0 1
  • Day 6: 1. 開頭不要重讀(不是看聲音大小,保持一聲)奏属;嘗試給自己做一下心理暗示囱皿,不要頭重腳輕嘱腥,虎頭蛇尾地去...
    蓬蓬豆的小馬甲呀閱讀 157評論 0 0
  • 朕已閱 這書也看了挺久了,不過看完也沒什么感覺分苇。去豆瓣上看了看書評组砚,挺多人罵作者,好奇怪∥谝叮現(xiàn)在的人寫書都大不如前人...
    青木729閱讀 186評論 0 0
  • 盯著手機(jī)屏幕幾十秒事扭,心中明明有千萬惆悵,卻發(fā)現(xiàn)自己不知道該寫些什么罐农。 感覺很糟糕涵亏,非常糟糕气筋,而且一切好像都在變得更...
    吳聊_Vicki閱讀 194評論 0 1