Jetpack使用(二)LiveData核心原理

寫在前面:Jetpack的更新速度非???,可能你一個月前看WorkManager是這樣用的,下個月這個使用方法就有可能被廢棄了(我看源碼的時候是遇到過的,而且源碼也變了,但核心原理是不變的),所以我們這一系列文章偏重講原理,使用就一帶而過(因為講了也沒用啊,會變的。。。。。,讀者使用最好看官方文檔官方文檔
,當然我這里講的也是截止到目前的最新用法)。

Jetpack使用(一)Lifecycles核心原理
Jetpack使用(二)LiveData核心原理
Jetpack使用(三)DataBinding核心原理
Jetpack使用(四)ViewModel核心原理
Jetpack使用(五)Navigation核心原理
Jetpack使用(六) WorkManager的4種用法

LiveData

LiveData 是一種可觀察的數(shù)據(jù)存儲器類。與常規(guī)的可觀察類不同,LiveData 具有生命周期感知能力,意指它遵循其他應用組件(如 Activity、Fragment 或 Service)的生命周期。這種感知能力可確保 LiveData 僅更新處于活躍生命周期狀態(tài)的應用組件觀察者。

  • 活躍狀態(tài):STARTED 或 RESUMED狀態(tài)
    因為LiveData只會更新處于前臺的activty的數(shù)據(jù),所以LiveData具有以下

優(yōu)點

  • 不會發(fā)生內(nèi)存泄露
    觀察者會綁定到 Lifecycle 對象,并在其關聯(lián)的生命周期遭到銷毀后進行自我清理。
  • 不會因 Activity 停止而導致崩潰
    如果觀察者的生命周期處于非活躍狀態(tài)(如返回棧中的 Activity),則它不會接收任何 LiveData 事件。
  • 不再需要手動處理生命周期
    界面組件只是觀察相關數(shù)據(jù),不會停止或恢復觀察。LiveData 將自動管理所有這些操作,因為它在觀察時可以感知相關的生命周期狀態(tài)變化。
  • 數(shù)據(jù)始終保持最新狀態(tài)
    如果生命周期變?yōu)榉腔钴S狀態(tài),它會在再次變?yōu)榛钴S狀態(tài)時接收最新的數(shù)據(jù)。例如,曾經(jīng)在后臺的 Activity 會在返回前臺后立即接收最新的數(shù)據(jù)。

具體使用

  • 創(chuàng)建 LiveData 對象
public class NameViewModel extends ViewModel {
    private MutableLiveData<String> currentName;
    public MutableLiveData<String> getCurrentName(){
        if(currentName==null){
            currentName=new MutableLiveData<>();
        }
        return currentName;
    }
}
  • 觀察 LiveData 對象
    public class NameActivity extends AppCompatActivity {

        private NameViewModel model;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            // Other code to setup the activity...

            // Get the ViewModel.
            model = ViewModelProviders.of(this).get(NameViewModel.class);

            // Create the observer which updates the UI.
            final Observer<String> nameObserver = new Observer<String>() {
                @Override
                public void onChanged(@Nullable final String newName) {
                    // Update the UI, in this case, a TextView.
                    nameTextView.setText(newName);
                }
            };

            // Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
            model.getCurrentName().observe(this, nameObserver);
        }
    }
  • 更新 LiveData 對象
 btn.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                String anotherName="小三爺";
                model.getCurrentName().setValue(anotherName);
            }
        });

注意:setValue在主線程使用;postValue在子線程使用

源碼分析

我們從observe做為入口

    @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);
    }

一開始先判斷observe觀察者是不是在主線程,不是在在主線程就會報異常,
然后獲得被觀察者的生命周期,我們這里是actvity,然后判斷是不是處于DESTROYED狀態(tài),如果處于DESTROYED直接返回,然后通過使用LifecycleBoundObserver把觀察者和被觀察者包裝在一起,然后再把wrapper放到mObservers集合里,最后通過addObserver添加觀察者,把觀察者和被觀察者的關系建立起來。
關系建立好之后,我們?nèi)タ词窃趺窗l(fā)送數(shù)據(jù)的,我們看到setValue的源碼

 @MainThread
    protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }

這個這個方法也是在主線程里調(diào)用的,一開始也判斷是不是主線程,然后mVersion版本++,這個變量后面再看,再把value存到LiveData的成員變量mData里,然后我們看到dispatchingValue方法里面,

  @SuppressWarnings("WeakerAccess") /* synthetic access */
    void dispatchingValue(@Nullable ObserverWrapper initiator) {
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            if (initiator != null) {
                considerNotify(initiator);
                initiator = null;
            } else {
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }

因為第一次傳的是空,所以走到for循環(huán)里面,通過迭代器從mObservers取出每個觀察者,然后調(diào)用considerNotify真正發(fā)送通知,


 @SuppressWarnings("unchecked")
    private void considerNotify(ObserverWrapper observer) {
        if (!observer.mActive) {
            return;
        }
        // Check latest state b4 dispatch. Maybe it changed state but we didn't 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 we've not received that event, we better not
        // notify for a more predictable notification order.
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        observer.mObserver.onChanged((T) mData);
    }

一開始observer如果不是活躍狀態(tài)(STARTED 或 RESUMED狀態(tài))直接退出,再判斷是不是應該被激活,如果不應該被激活,我們看看shouldBeActive方法

 @Override
        boolean shouldBeActive() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

我們看到這個方法就是判斷狀態(tài)是不是大于等于STARTED,通過上一篇文章我們知道,比STARTED大的就是RESUMED,所以這里只有是狀態(tài)STARTED或者RESUMED的時候才是返回 true的,所以這個if也就是判斷是不是處于活躍狀態(tài),如果不是活躍狀態(tài)進入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);
            }
        }
    }

這里就是在統(tǒng)計LiveData里有沒有活躍狀態(tài)的,如果有就執(zhí)行dispatchingValue,這次傳的就不是null了,而是具體的liveData對象了,所以又走到之前的dispatchingValue方法里,只是這次走的是不為null的判斷里,所以,這次再走到 if (observer.mLastVersion >= mVersion) {這個判斷里,我們知道m(xù)LastVersion和mVersion初始值都是-1,但之前mVersion++了,不會return,所以最后,執(zhí)行observer.mObserver.onChanged((T) mData);發(fā)送之前存的mData數(shù)據(jù)的操作。

  • 注意: if (initiator != null) 參數(shù)傳null和不傳null的區(qū)別就是如果傳null將會通知所有的觀察者,反之僅僅通知傳入的活躍的觀察者
    至此,我們LiveData的原理分析完了。

總結:LiveData通過addObserver綁定到Lifecycles上,所以擁有了感應生命周期的能力,而且LiveData只會去更新處于活躍狀態(tài)的應用組件觀察者,如果界面還在后臺,LiveData是不會去發(fā)送數(shù)據(jù)的,這樣做大大提高了app的性能。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容