中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android?Jetpack庫之LiveData組件怎么使用

發布時間:2022-07-22 13:36:58 來源:億速云 閱讀:160 作者:iii 欄目:開發技術

今天小編給大家分享一下Android Jetpack庫之LiveData組件怎么使用的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

LiveData簡介

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

LiveData用法

LiveData是一個數據容器,訂閱視圖的生命周期,在子線程通過postValue()切換到主線程來傳遞數據給觀察者,當視圖是活動的狀態下觀察者即可接受到數據,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")
                }
            }
        }
    }
}

數據訂閱過程

@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來構建一個LifecycleBoundObserver
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        //3,把observer存放到mObservers中
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        //4,如果existing不為空代表觀察者已經存在并且已經綁定了生命周期,拋一個Exception來提示                 
        if (existing != null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        //5,調用Lifecycle的addObserver()方法來訂閱生命周期
        owner.getLifecycle().addObserver(wrapper);
    }

1,先判斷當前訂閱數據這個操作是否是在主線程中執行,否則的話拋一個Exception

2,把owner,observer傳入到LifecycleBoundObserver構建出一個LifecycleBoundObserver對象

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

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

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

當我們的視圖的生命周期發生改變,LifecycleBoundObserver的onStateChange()方法就會被調用

PostValue過程

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

當調用postValue()方法是通過構建一個Handler并關聯主線程的Looper來post一個Runnable來回到主線程執行run方法里面的邏輯,而mPostValueRunnable的run()方法則調用了setValue()方法來實現數據的發送

SetValue過程

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

1,檢查當前是否在主線程

2, 每次調用setValue()方法版本號(mVersion)都進行累加

3,把需要新數據賦值給mData

4,調用dispatchingValue來執行數據下發

5,如果initiator不為null則直接給這個觀察者下發數據更新通知

6,否則遍歷所有的觀察者,逐個下發數據更新通知

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

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

9,比對數據版本號,如果當前observer的數據是最新數據則不需要下發

10,記錄數據版本號并通知observer數據更新,回調observer的onChanged()方法

生命周期變化

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

在訂閱數據那一刻(即調用LiveData.observer())就構建了一個LifecycleBoundObserver并且讓LifecycleBoundObserver訂閱了頁面生命周期,所以當頁面的生命周期發生改變,LifecycleBoundObserver的onStateChanged()方法都會被調用

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

2,更新狀態并下發數據

3,判斷當前observer的狀態跟新狀態是否一致,如果時是則不需要更新狀態以及數據

4,記錄當前observer的狀態

5,調用dispatchingValue()并傳入當前observer,執行準確下發數據業務

以上就是“Android Jetpack庫之LiveData組件怎么使用”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

汾西县| 西安市| 榆树市| 黔江区| 枣庄市| 辽中县| 绥阳县| 定边县| 永安市| 张掖市| 邵阳市| 黔东| 菏泽市| 安康市| 东港市| 怀化市| 大厂| 盘锦市| 明光市| 灵山县| 健康| 同江市| 永福县| 青铜峡市| 顺义区| 宜兰市| 广宗县| 财经| 罗江县| 红河县| 鹰潭市| 来安县| 朝阳区| 广元市| 武乡县| 贵南县| 荥经县| 原平市| 囊谦县| 永修县| 茂名市|