Android - 在Fragment中觀察LiveData時,為什么要使用viewLifecycleOwner

官網建議使用viewLifecycleOwner
在Fragment中對LiveData對象調用Observe方法的時候,如果傳遞的LifecycleOwner參數為this,也就是Fragment的時候,會受到AndroidStudio的提醒,要求使用viewLifecycleOwner:


fragment.png

從類型上來說,Fragment與viewLifecycleOwner的類型FragmentViewLifecycle兩者都繼承了LifecycleOwner,像之前那樣直接this,大部分情況下運行也是正常的,那么這里的Lint提醒是什么呢?

通過在官網尋找androidx.fragment:fragment的文檔,可以看到1.2.0版本更新的內容有一條:


26005601-ff3b75c18a8b2c79.png

可以知道,這肯定是有他的道理。我們來一起分析一下原因:

viewLifecycleOwner相關生命周期
找到viewLifecycleOwner相關代碼( 只看關鍵點 ):

//Fragment.java中
void performCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
        @Nullable Bundle savedInstanceState) {
mChildFragmentManager.noteStateNotSaved();
    mPerformedCreateView =true;
    mViewLifecycleOwner =new FragmentViewLifecycleOwner(); //此處創建了FragmentViewLifecycleOwner
    mView = onCreateView(inflater, container, savedInstanceState); //創建完成之后,調用了onCreateView()方法
    ... //省略無關代碼
}

//FragmentManager.java
private void destroyFragmentView(@NonNull Fragment fragment) {
    fragment.performDestroyView(); //此方法中執行了onDestroyView()方法
    fragment.mViewLifecycleOwner =null; //在執行完onDestroyView()方法之后,將viewLifecycleOwner置空
}

//Fragment.java
void performDestroyView() {
    ...
    onDestroyView(); // fragment.performDestroyView()方法調用中,執行了onDestroyView()方法
    ...
}

可以發現mViewLifecycleOwner的賦值在onCreateView()之前,置空在onDestroyView()之后,
mViewLifecycleOwner的注釋也說明了這點:
    // 這在performCreateView中初始化,在外部不可用
    // This is initialized in performCreateView and unavailable outside of the
    // onCreateView/onDestroyView生命周期
    // onCreateView/onDestroyView lifecycle
    @Nullable FragmentViewLifecycleOwner mViewLifecycleOwner;

正如類名所示,這個FragmentViewLifecycle代表的是Fragment中View的LifecycleOwner,Fragment中View的生命周期與Fragment本身并不相同。
看到這里,想必有些同學對Fragment的生命周期也半知半解,順便溫習一下:


Fragment.png

Fragment入back stack的過程會執行onDestroyView但不執行之后的onDestroy與onDetach,而出back stack是從onCreateView開始執行,而沒有之前的onAttach與onCreate。

LiveData的observe過程

溫習了相關生命周期后,下面來看一下LiveData的observe過程。

我們知道在LiveData的observe方法內,會將參數owner與observer包裝起來,使得observer的回調受owner的生命周期的影響,只有在owner處于活躍狀態才回調observer,而活躍狀態指的是當前owner的生命周期至少為STARTED,即如下(1)處,owner與observer的包裝類中否活躍的判斷方法。

    class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
        @NonNull
        final LifecycleOwner mOwner;
        LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
            super(observer);
            mOwner = owner;
        }
        @Override
        boolean shouldBeActive() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }//(1)
        @Override
        public void onStateChanged(@NonNull LifecycleOwner source,
                @NonNull Lifecycle.Event event) {
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(mObserver);//(2)
                return;
            }
            activeStateChanged(shouldBeActive());
        }
        ...
    }

可是,Fragment與Fragment中的View在活躍的生命周期狀態是一致的,這里的owner使用fragment還是viewLifecycleOwner并無不同,二者只有在onCreateView到onDestroyView之外有區別。

包裝類中的onStateChanged方法會執行observer的適時移除工作,而(2)處的移除observer正是在owner處于DESTROYED時發生的。對于Fragment,狀態會在onDestroyView執行前夕,變為DESTROYED,如下所示:

//Fragment.java 也對應了上邊的內容
    void performDestroyView() {
        mChildFragmentManager.dispatchDestroyView();
        if (mView != null) {
            mViewLifecycleOwner.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
        }
        mState = CREATED;
        onDestroyView();
        ...
    }

原因

此時,一切都解釋得通了,在Fragment中對LiveData對象調用observe方法時,使用viewLifecycleOwner代替this的原因是:Fragment與Fragment中的View的生命周期并不一致,需要讓observer感知Fragment中的View的生命周期而非Fragment,因此Android專門構造了Fragment中的View的LifecycleOwner,即viewLifecycleOwner。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。