Androidx 下 Fragment 懶加載的新實現

前言

年後最後一篇文章啦,在這裏先祝你們新年快樂~最重要的抽中全家福,明年繼續修福報🤣java

之前處理 Fragment 的懶加載,咱們一般會在 Fragment 中處理 setUserVisibleHint + onHiddenChanged 這兩個函數,而在 Androidx 模式下,咱們可使用 FragmentTransaction.setMaxLifecycle() 的方式來處理 Fragment 的懶加載。android

在本文章中,我會詳細介紹不一樣使用場景下兩種方案的差別。你們快拿好小板凳。一塊兒來學習新知識吧!git

本篇文章涉及到的 Demo,已上傳至Github---->傳送門github

老的懶加載處理方案

若是你熟悉老一套的 Fragment 懶加載機制,你能夠直接查看 Androix 懶加載相關章節緩存

add+show+hide 模式下的老方案

在沒有添加懶加載以前,只要使用 add+show+hide 的方式控制並顯示 Fragment, 那麼無論 Fragment 是否嵌套,在初始化後,若是只調用了add+show,同級下的 Fragment 的相關生命週期函數都會被調用。且調用的生命週期函數以下所示:網絡

onAttach -> onCreate -> onCreatedView -> onActivityCreated -> onStart -> onResumeapp

Fragment 完整生命週期:onAttach -> onCreate -> onCreatedView -> onActivityCreated -> onStart -> onResume -> onPause -> onStop -> onDestroyView -> onDestroy -> onDetachide

什麼是同級 Frament 呢?看下圖函數

同級Fragment.jpg

上圖中,都是使用 add+show+hide 的方式控制 Fragment,學習

在上圖兩種模式中:

  • Fragment_一、Fragment_二、Fragment_3 屬於同級 Fragment
  • Fragment_a、Fragment_b、Fragment_c 屬於同級 Fragment
  • Fragment_d、Fragment_e、Fragment_f 屬於同級 Fragment

那這種方式會帶來什麼問題呢?結合下圖咱們來分別分析。

show1.png

觀察上圖咱們能夠發現,同級的Fragment_一、Fragment_二、Fragment_3 都調用了 onAttach...onResume 系列方法,也就是說,若是咱們沒有對 Fragment 進行懶加載處理,那麼咱們就會平白無故的加載一些並不可見的 Fragment , 也就會形成用戶流量的無端消耗(咱們會在 Fragment 相關生命週期函數中,請求網絡或其餘數據操做)。

這裏"不可見的Fragment"是指,實際不可見可是相關可見生命週期函數(如 onResume 方法)被調用的 Fragment

若是使用嵌套 Fragment ,這種浪費流量的行爲就更明顯了。以本節的圖一爲例,當 Fragment_1 加載時,若是你在 Fragment_1 生命週期函數中使用 show+add+hide 的方式添加 Fragment_a、Fragment_b、Fragment_c , 那麼 Fragment_b 又會在其生命週期函數中繼續加載 Fragment_d、Fragment_e、Fragment_f

那如何解決這種問題呢?咱們繼續接着上面的例子走,當咱們 show Fragment_2,並 hide其餘 Fragment 時,對應 Fragment 的生命週期調用以下:

show2.png

從上圖中,咱們能夠看出 Fragment_2 與 Fragment_3 都調用了 onHiddenChanged 函數,該函數的官方 API 聲明以下:

/** * Called when the hidden state (as returned by {@link #isHidden()} of * the fragment has changed. Fragments start out not hidden; this will * be called whenever the fragment changes state from that. * @param hidden True if the fragment is now hidden, false otherwise. */
    public void onHiddenChanged(boolean hidden) {
    }
複製代碼

根據官方 API 的註釋,咱們大概能知道,當 Fragment 隱藏的狀態發生改變時,該函數將會被調用,若是當前 Fragment 隱藏, hidden 的值爲 true, 反之爲 false。最爲重要的是hidden 的值,能夠經過調用 isHidden() 函數獲取。

那麼結合上述知識點,咱們能推導出:

  • 由於 Fragment_1 的 隱藏狀態可見轉爲了避免可見,因此其 onHiddenChanged 函數被調用,同時 hidden 的值爲 true。
  • 同理對於 Fragment_2 ,由於其 隱藏狀態不可見轉爲了可見 ,因此其 hidden 值爲 false。
  • 對於 Fragment_3 ,由於其隱藏狀態從始至終都沒有發生變化,因此其 onHiddenChanged 函數並不會調用。

嗯,好像有點眉目了。不急,咱們繼續看下面的例子。

show Fragment_3 並 hide 其餘 Fragment ,對應生命週期函數調用以下所示:

show3.png

從圖中,咱們能夠看出,確實只有隱藏狀態發生了改變的 Fragment 其 onHiddenChanged 函數纔會調用,那麼結合以上知識點,咱們能得出以下重要結論:

只要經過 show+hide 方式控制 Fragment 的顯隱,那麼在第一次初始化後,Fragment 任何的生命週期方法都不會調用,只有 onHiddenChanged 方法會被調用。

那麼,假如咱們要在 add+show+hide 模式下控制 Fragment 的懶加載,咱們只須要作這兩步:

  • 咱們須要在 onResume() 函數中調用 isHidden() 函數,來處理默認顯示的 Fragment
  • onHiddenChanged 函數中控制其餘不可見的Fragment,

也就是這樣處理:

abstract class LazyFragment:Fragment(){

    private var isLoaded = false //控制是否執行懶加載

    override fun onResume() {
        super.onResume()
        judgeLazyInit()

    }
    override fun onHiddenChanged(hidden: Boolean) {
        super.onHiddenChanged(hidden)
        isVisibleToUser = !hidden
        judgeLazyInit()
    }

    private fun judgeLazyInit() {
        if (!isLoaded && !isHidden) {
            lazyInit()
            isLoaded = true
        }
    }

     override fun onDestroyView() {
        super.onDestroyView()
        isLoaded = false
    }

    //懶加載方法
    abstract fun lazyInit()
}
複製代碼

該懶加載的實現,是在 onResume 方法中操做,固然你能夠在其餘生命週期函數中控制。可是建議在該方法中執行懶加載。

ViewPager+Fragment 模式下的老方案

使用傳統方式處理 ViewPager 中 Fragment 的懶加載,咱們須要控制 setUserVisibleHint(boolean isVisibleToUser) 函數,該函數的聲明以下所示:

public void setUserVisibleHint(boolean isVisibleToUser) {}
複製代碼

該函數與以前咱們介紹的 onHiddenChanged() 做用很是類似,都是經過傳入的參數值來判斷當前 Fragment 是否對用戶可見,只是 onHiddenChanged() 是在 add+show+hide 模式下使用,而 setUserVisibleHint 是在 ViewPager+Fragment 模式下使用。

在本節中,咱們用 FragmentPagerAdapter + ViewPager 爲例,向你們講解如何實現 Fragment 的懶加載。

注意:在本例中沒有調用 setOffscreenPageLimit 方法去設置 ViewPager 預緩存的 Fragment 個數。默認狀況下 ViewPager 預緩存 Fragment 的個數爲 1

初始化 ViewPager 查看內部 Fragment 生命週期函數調用狀況:

viewpager1.png

觀察上圖,咱們能發現 ViePager 初始化時,默認會調用其內部 Fragment 的 setUserVisibleHint 方法,由於其預緩存 Fragment 個數爲 1 的緣由,因此只有 Fragment_1 與 Fragment_2 的生命週期函數被調用。

咱們繼續切換到 Fragment_2,查看各個Fragment的生命週期函數的調用變化。以下圖所示:

viewpage2.png

觀察上圖,咱們一樣發現 Fragment 的 setUserVisibleHint 方法被調用了,而且 Fragment_3 的一系列生命週期函數被調用了。繼續切換到 Fragment_3:

viewpager_3.png

觀察上圖能夠發現,Fragment_3 調用了 setUserVisibleHint 方法,繼續又切換到 Fragment_1,查看調用函數的變化:

viewpager4.png

由於以前在切換到 Fragment_3 時,Frafgment_1 已經走了 onDestoryView(圖二,藍色標記處) 方法,因此 Fragment_1 須要從新走一次生命週期。

那麼結合本節的三幅圖,咱們能得出如下結論:

  • 使用 ViewPager,切換回上一個 Fragment 頁面時(已經初始化完畢),不會回調任何生命週期方法以及onHiddenChanged(),只有 setUserVisibleHint(boolean isVisibleToUser) 會被回調。
  • setUserVisibleHint(boolean isVisibleToUser) 方法老是會優先於 Fragment 生命週期函數的調用。

因此若是咱們想對 ViewPager 中的 Fragment 懶加載,咱們須要這樣處理:

abstract class LazyFragment : Fragment() {

    /** * 是否執行懶加載 */
    private var isLoaded = false

    /** * 當前Fragment是否對用戶可見 */
    private var isVisibleToUser = false

    /** * 當使用ViewPager+Fragment形式會調用該方法時,setUserVisibleHint會優先Fragment生命週期函數調用, * 因此這個時候就,會致使在setUserVisibleHint方法執行時就執行了懶加載, * 而不是在onResume方法實際調用的時候執行懶加載。因此須要這個變量 */
    private var isCallResume = false

    override fun onResume() {
        super.onResume()
        isCallResume = true
        judgeLazyInit()
    }


    private fun judgeLazyInit() {
        if (!isLoaded && isVisibleToUser && isCallResume) {
            lazyInit()
            Log.d(TAG, "lazyInit:!!!!!!!")
            isLoaded = true
        }
    }

    override fun onHiddenChanged(hidden: Boolean) {
        super.onHiddenChanged(hidden)
        isVisibleToUser = !hidden
        judgeLazyInit()
    }

    //在Fragment銷燬View的時候,重置狀態
    override fun onDestroyView() {
        super.onDestroyView()
        isLoaded = false
        isVisibleToUser = false
        isCallResume = false
    }

    override fun setUserVisibleHint(isVisibleToUser: Boolean) {
        super.setUserVisibleHint(isVisibleToUser)
        this.isVisibleToUser = isVisibleToUser
        judgeLazyInit()
    }

    abstract fun lazyInit()
}
複製代碼

複雜 Fragment 嵌套的狀況

固然,在實際項目中,咱們可能會遇到更爲複雜的 Fragment 嵌套組合。好比 Fragment+Fragment、Fragment+ViewPager、ViewPager+ViewPager....等等。 以下圖所示:

複雜嵌套Fragment.jpg

對於以上場景,咱們就須要重寫咱們的懶加載,以支持不一樣嵌套組合模式下 Fragment 正確懶加載。咱們須要將 LazyFragment 修改爲以下這樣:

abstract class LazyFragment : Fragment() {

    /** * 是否執行懶加載 */
    private var isLoaded = false

    /** * 當前Fragment是否對用戶可見 */
    private var isVisibleToUser = false

    /** * 當使用ViewPager+Fragment形式會調用該方法時,setUserVisibleHint會優先Fragment生命週期函數調用, * 因此這個時候就,會致使在setUserVisibleHint方法執行時就執行了懶加載, * 而不是在onResume方法實際調用的時候執行懶加載。因此須要這個變量 */
    private var isCallResume = false

    /** * 是否調用了setUserVisibleHint方法。處理show+add+hide模式下,默承認見 Fragment 不調用 * onHiddenChanged 方法,進而不執行懶加載方法的問題。 */
    private var isCallUserVisibleHint = false

    override fun onResume() {
        super.onResume()
        isCallResume = true
        if (!isCallUserVisibleHint) isVisibleToUser = !isHidden
        judgeLazyInit()
    }


    private fun judgeLazyInit() {
        if (!isLoaded && isVisibleToUser && isCallResume) {
            lazyInit()
            Log.d(TAG, "lazyInit:!!!!!!!")
            isLoaded = true
        }
    }

    override fun onHiddenChanged(hidden: Boolean) {
        super.onHiddenChanged(hidden)
        isVisibleToUser = !hidden
        judgeLazyInit()
    }

    override fun onDestroyView() {
        super.onDestroyView()
        isLoaded = false
        isVisibleToUser = false
        isCallUserVisibleHint = false
        isCallResume = false
    }

    override fun setUserVisibleHint(isVisibleToUser: Boolean) {
        super.setUserVisibleHint(isVisibleToUser)
        this.isVisibleToUser = isVisibleToUser
        isCallUserVisibleHint = true
        judgeLazyInit()
    }

    abstract fun lazyInit()
}
複製代碼

Androidx 下的懶加載

雖然以前的方案就能解決輕鬆的解決 Fragment 的懶加載,但這套方案有一個最大的弊端,就是不可見的 Fragment 執行了 onResume() 方法。onResume 方法設計的初衷,難道不是當前 Fragment 能夠和用戶進行交互嗎?你他媽既不可見,又不能和用戶進行交互,你執行 onResume 方法幹嗎?

基於此問題,Google 在 Androidx 在 FragmentTransaction 中增長了 setMaxLifecycle 方法來控制 Fragment 所能調用的最大的生命週期函數。以下所示:

/** * Set a ceiling for the state of an active fragment in this FragmentManager. If fragment is * already above the received state, it will be forced down to the correct state. * * <p>The fragment provided must currently be added to the FragmentManager to have it's * Lifecycle state capped, or previously added as part of this transaction. The * {@link Lifecycle.State} passed in must at least be {@link Lifecycle.State#CREATED}, otherwise * an {@link IllegalArgumentException} will be thrown.</p> * * @param fragment the fragment to have it's state capped. * @param state the ceiling state for the fragment. * @return the same FragmentTransaction instance */
    @NonNull
    public FragmentTransaction setMaxLifecycle(@NonNull Fragment fragment, @NonNull Lifecycle.State state) {
        addOp(new Op(OP_SET_MAX_LIFECYCLE, fragment, state));
        return this;
    }
複製代碼

根據官方的註釋,咱們能知道,該方法能夠設置活躍狀態下 Fragment 最大的狀態,若是該 Fragment 超過了設置的最大狀態,那麼會強制將 Fragment 降級到正確的狀態。

那如何使用該方法呢?咱們先看該方法在 Androidx 模式下 ViewPager+Fragment 模式下的使用例子。

ViewPager+Fragment 模式下的方案

在 FragmentPagerAdapter 與 FragmentStatePagerAdapter 新增了含有 behavior 字段的構造函數,以下所示:

public FragmentPagerAdapter(@NonNull FragmentManager fm, @Behavior int behavior) {
        mFragmentManager = fm;
        mBehavior = behavior;
    }

  public FragmentStatePagerAdapter(@NonNull FragmentManager fm, @Behavior int behavior) {
        mFragmentManager = fm;
        mBehavior = behavior;
    }

複製代碼

其中 Behavior 的聲明以下:

@Retention(RetentionPolicy.SOURCE)
    @IntDef({BEHAVIOR_SET_USER_VISIBLE_HINT, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT})
    private @interface Behavior { }

     /** * Indicates that {@link Fragment#setUserVisibleHint(boolean)} will be called when the current * fragment changes. * * @deprecated This behavior relies on the deprecated * {@link Fragment#setUserVisibleHint(boolean)} API. Use * {@link #BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT} to switch to its replacement, * {@link FragmentTransaction#setMaxLifecycle}. * @see #FragmentPagerAdapter(FragmentManager, int) */
    @Deprecated
    public static final int BEHAVIOR_SET_USER_VISIBLE_HINT = 0;

    /** * Indicates that only the current fragment will be in the {@link Lifecycle.State#RESUMED} * state. All other Fragments are capped at {@link Lifecycle.State#STARTED}. * * @see #FragmentPagerAdapter(FragmentManager, int) */
    public static final int BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT = 1;
複製代碼

從官方的註釋聲明中,咱們能獲得以下兩條結論:

  • 若是 behavior 的值爲 BEHAVIOR_SET_USER_VISIBLE_HINT,那麼當 Fragment 對用戶的可見狀態發生改變時,setUserVisibleHint 方法會被調用。
  • 若是 behavior 的值爲 BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT ,那麼當前選中的 Fragment 在 Lifecycle.State#RESUMED 狀態 ,其餘不可見的 Fragment 會被限制在 Lifecycle.State#STARTED 狀態。

那 BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT 這個值到底有什麼做用呢?咱們看下面的例子:

在該例子中設置了 ViewPager 的適配器爲 FragmentPagerAdapter 且 behavior 值爲 BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT

默認初始化ViewPager,Fragment 生命週期以下所示:

androix1.png

切換到 Fragment_2 時,日誌狀況以下所示:

androix2.png

切換到 Fragment_3 時,日誌狀況以下所示:

androidx3.png

由於篇幅的緣由,本文沒有在講解 FragmentStatePagerAdapter 設置 behavior 下的使用狀況,可是原理以及生命週期函數調用狀況同樣,感興趣的小夥伴,能夠根據 AndroidxLazyLoad 項目自行測試。

觀察上述例子,咱們能夠發現,使用了 BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT 後,確實只有當前可見的 Fragment 調用了 onResume 方法。而致使產生這種改變的緣由,是由於 FragmentPagerAdapter 在其 setPrimaryItem 方法中調用了 setMaxLifecycle 方法,以下所示:

public void setPrimaryItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
        Fragment fragment = (Fragment)object;
        //若是當前的fragment不是當前選中並可見的Fragment,那麼就會調用
        // setMaxLifecycle 設置其最大生命週期爲 Lifecycle.State.STARTED
        if (fragment != mCurrentPrimaryItem) {
            if (mCurrentPrimaryItem != null) {
                mCurrentPrimaryItem.setMenuVisibility(false);
                if (mBehavior == BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
                    if (mCurTransaction == null) {
                        mCurTransaction = mFragmentManager.beginTransaction();
                    }
                    mCurTransaction.setMaxLifecycle(mCurrentPrimaryItem, Lifecycle.State.STARTED);
                } else {
                    mCurrentPrimaryItem.setUserVisibleHint(false);
                }
            }
        //對於其餘非可見的Fragment,則設置其最大生命週期爲
        //Lifecycle.State.RESUMED
            fragment.setMenuVisibility(true);
            if (mBehavior == BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
                if (mCurTransaction == null) {
                    mCurTransaction = mFragmentManager.beginTransaction();
                }
                mCurTransaction.setMaxLifecycle(fragment, Lifecycle.State.RESUMED);
            } else {
                fragment.setUserVisibleHint(true);
            }

            mCurrentPrimaryItem = fragment;
        }
    }
複製代碼

既然在上述條件下,只有實際可見的 Fragment 會調用 onResume 方法, 那是否是爲咱們提供了 ViewPager 下實現懶加載的新思路呢?也就是咱們能夠這樣實現 Fragment 的懶加載:

abstract class LazyFragment : Fragment() {

    private var isLoaded = false

    override fun onResume() {
        super.onResume()
        if (!isLoaded) {
            lazyInit()
            Log.d(TAG, "lazyInit:!!!!!!!")
            isLoaded = true
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        isLoaded = false
    }

    abstract fun lazyInit()
}
複製代碼

add+show+hide 模式下的新方案

雖然咱們實現了Androidx 包下 ViewPager下的懶加載,可是咱們仍然要考慮 add+show+hide 模式下的 Fragment 懶加載的狀況,基於 ViewPager 在 setPrimaryItem 方法中的思路,咱們能夠在調用 add+show+hide 時,這樣處理:

完整的代碼請點擊--->ShowHideExt

/** * 使用add+show+hide模式加載fragment * * 默認顯示位置[showPosition]的Fragment,最大Lifecycle爲Lifecycle.State.RESUMED * 其餘隱藏的Fragment,最大Lifecycle爲Lifecycle.State.STARTED * *@param containerViewId 容器id *@param showPosition fragments *@param fragmentManager FragmentManager *@param fragments 控制顯示的Fragments */
private fun loadFragmentsTransaction( @IdRes containerViewId: Int, showPosition: Int, fragmentManager: FragmentManager, vararg fragments: Fragment ) {
    if (fragments.isNotEmpty()) {
        fragmentManager.beginTransaction().apply {
            for (index in fragments.indices) {
                val fragment = fragments[index]
                add(containerViewId, fragment, fragment.javaClass.name)
                if (showPosition == index) {
                    setMaxLifecycle(fragment, Lifecycle.State.RESUMED)
                } else {
                    hide(fragment)
                    setMaxLifecycle(fragment, Lifecycle.State.STARTED)
                }
            }

        }.commit()
    } else {
        throw IllegalStateException(
            "fragments must not empty"
        )
    }
}

/** 顯示須要顯示的Fragment[showFragment],並設置其最大Lifecycle爲Lifecycle.State.RESUMED。 * 同時隱藏其餘Fragment,並設置最大Lifecycle爲Lifecycle.State.STARTED * @param fragmentManager * @param showFragment */
private fun showHideFragmentTransaction(fragmentManager: FragmentManager, showFragment: Fragment) {
    fragmentManager.beginTransaction().apply {
        show(showFragment)
        setMaxLifecycle(showFragment, Lifecycle.State.RESUMED)

        //獲取其中全部的fragment,其餘的fragment進行隱藏
        val fragments = fragmentManager.fragments
        for (fragment in fragments) {
            if (fragment != showFragment) {
                hide(fragment)
                setMaxLifecycle(fragment, Lifecycle.State.STARTED)
            }
        }
    }.commit()
}
複製代碼

上述代碼的實現也很是簡單:

  • 將須要顯示的 Fragment ,在調用 add 或 show 方法後,setMaxLifecycle(showFragment, Lifecycle.State.RESUMED)
  • 將須要隱藏的 Fragment ,在調用 hide 方法後,setMaxLifecycle(fragment, Lifecycle.State.STARTED)

結合上述操做模式,查看使用 setMaxLifecycle 後,Fragment 生命週期函數調用的狀況。

add Fragment_一、Fragment_二、Fragment_3,並 hide Fragment_2,Fragment_3 :

show_new1.png

show Fragment_2,hide 其餘 Fragment:

show_new2.png

show Fragment_3 hide 其餘 Fragment:

show_new3.png

參考上圖,好像真的也能處理懶加載!!!!!美滋滋

並不完美的 setMaxLifecycle

當我第一次使用 setMaxLifycycle 方法時,我也和你們同樣以爲萬事大吉。但這套方案仍然有點點瑕疵,當 Fragment 的嵌套時,即便使用了 setMaxLifycycle 方法,第一次初始化時,同級不可見的Fragment,仍然 TMD 要調用可見生命週期方法。看下面的例子:

瑕疵.png

不知道是不是谷歌大大沒有考慮到 Fragment 嵌套的狀況,因此這裏咱們要對以前的方案就行修改,也就是以下所示:

abstract class LazyFragment : Fragment() {

    private var isLoaded = false

    override fun onResume() {
        super.onResume()
        //增長了Fragment是否可見的判斷
        if (!isLoaded && !isHidden) {
            lazyInit()
            Log.d(TAG, "lazyInit:!!!!!!!")
            isLoaded = true
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        isLoaded = false
    }

    abstract fun lazyInit()

}
複製代碼

在上述代碼中,由於同級的 Fragment 在嵌套模式下,仍然要調用 onResume 方法,因此咱們增長了 Fragment 可見性的判斷,這樣就能保證嵌套模式下,新方案也能完美的支持 Fragment 的懶加載。

ViewPager2 的處理方案

ViewPager2 自己就支持對實際可見的 Fragment 才調用 onResume 方法。關於 ViewPager2 的內部機制。感興趣的小夥伴能夠自行查看源碼。

關於 ViewPager2 的懶加載測試,已上傳至 AndroidxLazyLoad,你們能夠結合項目查看Log日誌。

兩種方式的對比與總結

老一套的懶加載

  • 優勢:不用去控制 FragmentManager的 add+show+hide 方法,全部的懶加載都是在Fragment 內部控制,也就是控制 setUserVisibleHint + onHiddenChanged 這兩個函數。
  • 缺點:實際不可見的 Fragment,其 onResume 方法任然會被調用,這種反常規的邏輯,沒法容忍。

新一套的懶加載(Androidx下setMaxLifecycle)

  • 優勢:在非特殊的狀況下(缺點1),只有實際的可見 Fragment,其 onResume 方法纔會被調用,這樣才符合方法設計的初衷。
  • 缺點:
    1. 對於 Fragment 的嵌套,及時使用了 setMaxLifecycle 方法。同級不可見的Fragment, 仍然要調用 onResume 方法。
    2. 須要在原有的 add+show+hide 方法中,繼續調用 setMaxLifecycle 方法來控制Fragment 的最大生命狀態。

最後

這兩種方案的優缺點已經很是明顯了,到底該選擇何種懶加載模式,仍是要基於你們的意願,做者我更傾向於使用新的方案。關於 Fragment 的懶加載實現,很是願意聽到你們不一樣的聲音,若是你有更好的方案,能夠在評論區留下您的 idea,期待您的回覆。若是您以爲本篇文章對你有所幫助,請不要吝嗇你的關注與點贊。ღ( ´・ᴗ・` )比心

相關文章
相關標籤/搜索