Androidx 下 Fragment 懶加載的新實現

閱讀前請點擊右上角“關注”,每天免費獲取Android知識解析及面試解答。Android架構解析,只做職場乾貨,完全免費分享!

Androidx 下 Fragment 懶加載的新實現

前言

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

在本文章中,我會詳細介紹不同使用場景下兩種方案的差異。大家快拿好小板凳。一起來學習新知識吧!

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

老的懶加載處理方案

如果你熟悉老一套的 Fragment 懶加載機制,你可以直接查看 Androix 懶加載相關章節

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

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

onAttach -> onCreate -> onCreatedView -> onActivityCreated -> onStart -> onResume

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

什麼是同級 Frament 呢?看下圖

Androidx 下 Fragment 懶加載的新實現

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

在上圖兩種模式中:

  • Fragment_1、Fragment_2、Fragment_3 屬於同級 Fragment
  • Fragment_a、Fragment_b、Fragment_c 屬於同級 Fragment
  • Fragment_d、Fragment_e、Fragment_f 屬於同級 Fragment

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

Androidx 下 Fragment 懶加載的新實現

觀察上圖我們可以發現,同級的Fragment_1、Fragment_2、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 的生命週期調用如下:

Androidx 下 Fragment 懶加載的新實現

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

<code>    /**
* 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) {
}

/<code>

根據官方 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 ,對應生命週期函數調用如下所示:

Androidx 下 Fragment 懶加載的新實現

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

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

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

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

也就是這樣處理:

<code>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()
}

/<code>

該懶加載的實現,是在 onResume 方法中操作,當然你可以在其他生命週期函數中控制。但是建議在該方法中執行懶加載。

ViewPager+Fragment 模式下的老方案

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

<code>    public void setUserVisibleHint(boolean isVisibleToUser) {}

/<code>

該函數與之前我們介紹的 onHiddenChanged() 作用非常相似,都是通過傳入的參數值來判斷當前 Fragment 是否對用戶可見,只是 onHiddenChanged() 是在 add+show+hide 模式下使用,而 setUserVisibleHint 是在 ViewPager+Fragment 模式下使用。

在本節中,我們用 FragmentPagerAdapter + ViewPager 為例,向大家講解如何實現 Fragment 的懶加載。

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

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

Androidx 下 Fragment 懶加載的新實現

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

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

Androidx 下 Fragment 懶加載的新實現

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

Androidx 下 Fragment 懶加載的新實現

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

Androidx 下 Fragment 懶加載的新實現

因為之前在切換到 Fragment_3 時,Frafgment_1 已經走了 onDestoryView(圖二,藍色標記處) 方法,所以 Fragment_1 需要重新走一次生命週期。

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

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

所以如果我們想對 ViewPager 中的 Fragment 懶加載,我們需要這樣處理:

<code>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()
}

/<code>

複雜 Fragment 嵌套的情況

當然,在實際項目中,我們可能會遇到更為複雜的 Fragment 嵌套組合。比如 Fragment+Fragment、Fragment+ViewPager、ViewPager+ViewPager….等等。如下圖所示:

Androidx 下 Fragment 懶加載的新實現

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

<code>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()
}

/<code>

Androidx 下的懶加載

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

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

<code>   /**
* 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.
*
*

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.


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

/<code>

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

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

ViewPager+Fragment 模式下的方案

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

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

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

/<code>

其中 Behavior 的聲明如下:

<code>   @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;

/<code>

從官方的註釋聲明中,我們能得到如下兩條結論:

  • 如果 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 生命週期如下所示:

Androidx 下 Fragment 懶加載的新實現

切換到 Fragment_2 時,日誌情況如下所示:

Androidx 下 Fragment 懶加載的新實現

切換到 Fragment_3 時,日誌情況如下所示:

Androidx 下 Fragment 懶加載的新實現

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

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

<code>    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;
}
}

/<code>

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

<code>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()
}

/<code>

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

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

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

<code>/**
* 使用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()
}

/<code>

上述代碼的實現也非常簡單:

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

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

add Fragment_1、Fragment_2、Fragment_3,並 hide Fragment_2,Fragment_3:

Androidx 下 Fragment 懶加載的新實現

show Fragment_2,hide 其他 Fragment:

Androidx 下 Fragment 懶加載的新實現

show Fragment_3 hide 其他 Fragment:

Androidx 下 Fragment 懶加載的新實現

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

並不完美的 setMaxLifecycle

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

Androidx 下 Fragment 懶加載的新實現

不知道是否是谷歌大大沒有考慮到 Fragment 嵌套的情況,所以這裡我們要對之前的方案就行修改,也就是如下所示:

<code>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()

}

/<code>

在上述代碼中,因為同級的 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 方法才會被調用,這樣才符合方法設計的初衷。
  • 缺點:對於 Fragment 的嵌套,及時使用了 setMaxLifecycle 方法。同級不可見的Fragment, 仍然要調用 onResume 方法。需要在原有的 add+show+hide 方法中,繼續調用 setMaxLifecycle 方法來控制Fragment 的最大生命狀態。

最後

這兩種方案的優缺點已經非常明顯了,到底該選擇何種懶加載模式,還是要基於大家的意願,作者我更傾向於使用新的方案。關於 Fragment 的懶加載實現,非常願意聽到大家不同的聲音,如果你有更好的方案,可以在評論區留下您的 idea,期待您的回覆。


分享到:


相關文章: