欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android?Jetpack庫剖析之LiveData組件篇

 更新時間:2022年07月22日 09:48:28   作者:豬飛啦~  
LiveData是Jetpack組件的一部分,更多的時候是搭配ViewModel來使用,相對于Observable,LiveData的最大優(yōu)勢是其具有生命感知的,換句話說,LiveData可以保證只有在組件( Activity、Fragment、Service)處于活動生命周期狀態(tài)的時候才會更新數(shù)據(jù)

LiveData簡介

在日常安卓開發(fā)中,一些耗時的操比如列網(wǎng)絡(luò)請求,數(shù)據(jù)庫讀寫都不能在主線程執(zhí)行,必須開一條子線程去執(zhí)行這些耗時操作,但我們往往需要在這些耗時操作執(zhí)行完畢后更新UI,但安卓不能在子線程進(jìn)行UI的更新,這時我們只能通過創(chuàng)建一個Handler來切回到主線程進(jìn)行UI的更新,直到LiveData出現(xiàn),LiveData是一個可被觀察的數(shù)據(jù)容器,它將數(shù)據(jù)包裝起來,使數(shù)據(jù)成為被觀察者。當(dāng)數(shù)據(jù)發(fā)生改變時,觀察者能夠及時得到通知。

LiveData用法

LiveData是一個數(shù)據(jù)容器,訂閱視圖的生命周期,在子線程通過postValue()切換到主線程來傳遞數(shù)據(jù)給觀察者,當(dāng)視圖是活動的狀態(tài)下觀察者即可接受到數(shù)據(jù),LiveData是一個典型的觀察者模式。

class MainActivity : AppCompatActivity() {
    private val mLiveData = MutableLiveData<String>()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding = ActivityMainBinding.inflate(LayoutInflater.from(baseContext))
        setContentView(binding.root)
        mLiveData.observe(this, {
            binding.tvContent.text = it
        })
        Thread(BackgroundThread(mLiveData)).start()
    }
    private class BackgroundThread(liveData: MutableLiveData<String>) : Runnable {
        private val mLive = WeakReference(liveData)
        override fun run() {
            mLive.apply {
                get()?.apply {
                    postValue("hello LiveData")
                }
            }
        }
    }
}

數(shù)據(jù)訂閱過程

@MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        //1,判斷是否在主線程
        assertMainThread("observe");
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        //2,通過owner,observer來構(gòu)建一個LifecycleBoundObserver
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        //3,把observer存放到mObservers中
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        //4,如果existing不為空代表觀察者已經(jīng)存在并且已經(jīng)綁定了生命周期,拋一個Exception來提示                 
        if (existing != null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        //5,調(diào)用Lifecycle的addObserver()方法來訂閱生命周期
        owner.getLifecycle().addObserver(wrapper);
    }

1,先判斷當(dāng)前訂閱數(shù)據(jù)這個操作是否是在主線程中執(zhí)行,否則的話拋一個Exception

2,把owner,observer傳入到LifecycleBoundObserver構(gòu)建出一個LifecycleBoundObserver對象

3,調(diào)用mObservers.putIfAbsent()方法把觀察者放到觀察者集合中,mObservers是SafeIterableMap類型的集合類似Map,但它是通過鏈表的方式來實現(xiàn)Map接口,SafeIterableMap.putIfAbsent()方法與Map.put()方法不一樣,如果根據(jù)key獲取的value不為null,就將當(dāng)前的value返回,如果為null,就將當(dāng)前的鍵值對存儲起來,然后返回一個null

4,existing不為null,代表Observer存在,就拋一個Exception來提示開發(fā)者:無法添加具有不同生命周期的同一觀察者

5,existing為null,代表observer不存在,添加觀察者來觀察生命周期擁有者的生命周期,

當(dāng)我們的視圖的生命周期發(fā)生改變,LifecycleBoundObserver的onStateChange()方法就會被調(diào)用

PostValue過程

protected void postValue(T value) {
        boolean postTask;
        //判斷當(dāng)前是否正在下發(fā)數(shù)據(jù)
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        //如果正在下發(fā)數(shù)據(jù)則繼續(xù)下發(fā)數(shù)據(jù)
        if (!postTask) {
            return;
        }
        //構(gòu)建Handler并關(guān)聯(lián)主線程的Looper,回到主線程執(zhí)行run方法中的邏輯
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }
private final Runnable mPostValueRunnable = new Runnable() {
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            //在主線程中調(diào)用setValue來執(zhí)行數(shù)據(jù)下發(fā)邏輯
            //noinspection unchecked
            setValue((T) newValue);
        }
    };

當(dāng)調(diào)用postValue()方法是通過構(gòu)建一個Handler并關(guān)聯(lián)主線程的Looper來post一個Runnable來回到主線程執(zhí)行run方法里面的邏輯,而mPostValueRunnable的run()方法則調(diào)用了setValue()方法來實現(xiàn)數(shù)據(jù)的發(fā)送

SetValue過程

@MainThread
    protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }
void dispatchingValue(@Nullable ObserverWrapper initiator) {
        //1,判斷當(dāng)前是正在下發(fā)數(shù)據(jù)
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            //2,如果initiator不為空直接給initiator發(fā)送數(shù)據(jù)更新通知
            if (initiator != null) {
                considerNotify(initiator);
                initiator = null;
            } else {
                /,3,否則遍歷所有observer
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    /4,發(fā)送數(shù)據(jù)更新通知
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }
private void considerNotify(ObserverWrapper observer) {
        5,如果當(dāng)前observer不是活動狀態(tài),不下發(fā)數(shù)據(jù)
        if (!observer.mActive) {
            return;
        }
        6,如果當(dāng)前observer的狀態(tài)至少不是started狀態(tài)(可見狀態(tài)),resumed比started高一個級別(可觸摸狀態(tài))則不下發(fā)數(shù)據(jù)
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        7,判斷數(shù)據(jù)版本號 如果當(dāng)前observer的數(shù)據(jù)是最新的 則不下發(fā)數(shù)據(jù)
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        8,記錄最新數(shù)據(jù)版本號
        observer.mLastVersion = mVersion;
        
        9,通知數(shù)據(jù)更新
        observer.mObserver.onChanged((T) mData);
    }
     @Override
        boolean shouldBeActive() {
            判斷當(dāng)前狀態(tài)是否>=STARTED
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

1,檢查當(dāng)前是否在主線程

2, 每次調(diào)用setValue()方法版本號(mVersion)都進(jìn)行累加

3,把需要新數(shù)據(jù)賦值給mData

4,調(diào)用dispatchingValue來執(zhí)行數(shù)據(jù)下發(fā)

5,如果initiator不為null則直接給這個觀察者下發(fā)數(shù)據(jù)更新通知

6,否則遍歷所有的觀察者,逐個下發(fā)數(shù)據(jù)更新通知

7,判斷當(dāng)前的observer是否為活動狀態(tài),不是活動狀態(tài)不下發(fā)數(shù)據(jù),這也就是為什么我們界面不可見時數(shù)據(jù)不會更新的原因(onStop狀態(tài))

8,判斷當(dāng)前的observer是否是resumed狀態(tài),不是resumed狀態(tài)不下發(fā)數(shù)據(jù),這就是為什么當(dāng)我們的頁面可見但不可觸摸時數(shù)據(jù)不更新的原因(onPause狀態(tài))

9,比對數(shù)據(jù)版本號,如果當(dāng)前observer的數(shù)據(jù)是最新數(shù)據(jù)則不需要下發(fā)

10,記錄數(shù)據(jù)版本號并通知observer數(shù)據(jù)更新,回調(diào)observer的onChanged()方法

生命周期變化

@Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            1,如果當(dāng)前的狀態(tài)為destroyed就移除observer
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
            2,更新狀態(tài)并下發(fā)數(shù)據(jù)
            activeStateChanged(shouldBeActive());
        }
void activeStateChanged(boolean newActive) {
            3,如果新狀態(tài)和當(dāng)前狀態(tài)一致的話不需要更新
            if (newActive == mActive) {
                return;
            }
            4,記錄新狀態(tài)
            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();
            }
            5,如果是活動狀態(tài) 下發(fā)數(shù)據(jù)
            if (mActive) {
                dispatchingValue(this);
            }
        }

在訂閱數(shù)據(jù)那一刻(即調(diào)用LiveData.observer())就構(gòu)建了一個LifecycleBoundObserver并且讓LifecycleBoundObserver訂閱了頁面生命周期,所以當(dāng)頁面的生命周期發(fā)生改變,LifecycleBoundObserver的onStateChanged()方法都會被調(diào)用

1,如果當(dāng)前頁面的狀態(tài)為destroyed(即銷毀狀態(tài)),則移除觀察者

2,更新狀態(tài)并下發(fā)數(shù)據(jù)

3,判斷當(dāng)前observer的狀態(tài)跟新狀態(tài)是否一致,如果時是則不需要更新狀態(tài)以及數(shù)據(jù)

4,記錄當(dāng)前observer的狀態(tài)

5,調(diào)用dispatchingValue()并傳入當(dāng)前observer,執(zhí)行準(zhǔn)確下發(fā)數(shù)據(jù)業(yè)務(wù)

到此這篇關(guān)于Android Jetpack庫剖析之LiveData組件篇的文章就介紹到這了,更多相關(guān)Android LiveData內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Android仿淘寶物流信息TimeLineView

    Android仿淘寶物流信息TimeLineView

    這篇文章主要為大家詳細(xì)介紹了Android仿淘寶物流信息TimeLineView的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-02-02
  • Android編程中圖片特效處理方法小結(jié)

    Android編程中圖片特效處理方法小結(jié)

    這篇文章主要介紹了Android編程中圖片特效處理方法,實例總結(jié)了Android實現(xiàn)圖片的轉(zhuǎn)換、縮放、圓角及倒影等效果的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-10-10
  • Android實現(xiàn)底部彈出PopupWindow背景逐漸變暗效果

    Android實現(xiàn)底部彈出PopupWindow背景逐漸變暗效果

    這篇文章主要為大家詳細(xì)介紹了Android實現(xiàn)底部彈出PopupWindow背景逐漸變暗效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • 在Visual Studio上構(gòu)建C++的GUI框架wxWidgets的開發(fā)環(huán)境

    在Visual Studio上構(gòu)建C++的GUI框架wxWidgets的開發(fā)環(huán)境

    這篇文章主要介紹了Visual Studio上構(gòu)件C++的GUI框架wxWidgets開發(fā)環(huán)境的方法,wxWidgets是一個跨多個系統(tǒng)平臺的圖形化界面開發(fā)框架,并且可用語言不限于C++,需要的朋友可以參考下
    2016-04-04
  • Android 自定義輸入手機號自動添加分隔符

    Android 自定義輸入手機號自動添加分隔符

    這篇文章主要介紹了Android 自定義輸入手機號自動添加分隔符的實例代碼,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2017-05-05
  • Android scrollToTop實現(xiàn)點擊回到頂部(兼容PullTorefreshScrollview)

    Android scrollToTop實現(xiàn)點擊回到頂部(兼容PullTorefreshScrollview)

    當(dāng)頁面滑動到底部,出現(xiàn)回到頂部的按鈕相信對大家來說并不陌生,下面這篇文章主要介紹了關(guān)于Android scrollToTop實現(xiàn)點擊回到頂部,并兼容PullTorefreshScrollview的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒。
    2017-03-03
  • Android Handler的詳解及實例

    Android Handler的詳解及實例

    這篇文章主要介紹了Android Handler的詳解及實例的相關(guān)資料,需要的朋友可以參考下
    2017-07-07
  • Android入門教程之創(chuàng)建樣式與主題

    Android入門教程之創(chuàng)建樣式與主題

    通過這篇文章你將學(xué)到如何創(chuàng)建自定義的樣式和主題,并且你還能學(xué)到如何使用Android Studio的工具和快捷方式來加快樣式的創(chuàng)建。下面來一起看看吧。
    2016-08-08
  • java反射android的r文件的示例

    java反射android的r文件的示例

    這篇文章主要介紹了java反射android的r文件的示例,動態(tài)取得R文件的int值,需要的朋友可以參考下
    2014-04-04
  • AndroidStudio 如何使用aar詳解

    AndroidStudio 如何使用aar詳解

    本文主要介紹AndroidStudio 如何使用aar的資料,這里整理了詳細(xì)的資料,幫助大家學(xué)習(xí)理解此部分的知識,有需要的小伙伴可以參考下
    2016-09-09

最新評論