日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

判断当前界面是该fragment_学不动也要学!探究Fragment延迟加载的前世今生

發(fā)布時(shí)間:2024/9/15 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 判断当前界面是该fragment_学不动也要学!探究Fragment延迟加载的前世今生 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

碼個(gè)蛋(codeegg)?第?852?次推文

作者:一包純牛奶鏈接:https://juejin.im/post/5e085dafe51d45580769a1eb

碼妞看世界

大家普遍對(duì)于Fragment懶加載的問(wèn)題比較關(guān)心,其實(shí),對(duì)于Fragment懶加載問(wèn)題的處理由來(lái)已久,網(wǎng)上不乏相關(guān)的優(yōu)秀文章。但是,由于Fragment生命周期的原因使得懶加載問(wèn)題的處理并不是那么的優(yōu)雅。顯然,Google也意識(shí)到了問(wèn)題所在。

因此,在Androidx的庫(kù)中對(duì)于Fragment的生命周期狀態(tài)的控制進(jìn)行了深度優(yōu)化,使得我們更容易的去管控Fragment的生命周期,也使得我們更容易的去處理懶加載問(wèn)題。但是,前提條件是我們要了解Google對(duì)于Fragment做了哪些優(yōu)化。那么就讓我們借此機(jī)會(huì)一起來(lái)探究一下吧!( 懶加載稱作延遲加載我覺(jué)得更貼切一些,所以下文就統(tǒng)稱為延遲加載了。 )

一、Fragment延遲加載的前世

雖然本篇文章是對(duì)于Fragment新特性的探究,但是我覺(jué)得寫文章總要有個(gè)因果。也為了照顧一下還不太了解什么是延遲加載的同學(xué)。我們還是先來(lái)了解一下延遲加載,順便回顧一下Fragment延遲加載的舊方案。

1. 為什么要對(duì)Fragment做延遲加載?

首先,我們要搞清楚一個(gè)問(wèn)題。“Fragment延遲加載“中的“延遲”并不指的是延遲加載Fragment,而是延遲加載Fragment中的數(shù)據(jù)。對(duì)于Fragment的使用通常我們會(huì)結(jié)合ViewPager,ViewPager會(huì)默認(rèn)在當(dāng)前頁(yè)面的左右兩邊至少預(yù)加載一個(gè)頁(yè)面以保證ViewPager的流暢性。

我們假設(shè)在ViewPager的所有Fragment中都存在網(wǎng)絡(luò)請(qǐng)求,當(dāng)我們打開(kāi)這個(gè)頁(yè)面的時(shí)候由于ViewPager的預(yù)加載原因,即使在其它Fragment不可見(jiàn)的情況下也會(huì)去進(jìn)行網(wǎng)絡(luò)請(qǐng)求加載數(shù)據(jù)。而如果此時(shí)用戶根本就沒(méi)有去滑動(dòng)ViewPager就退出了應(yīng)用或者切換到了其他頁(yè)面。那么對(duì)于這個(gè)不可見(jiàn)的Fragment中的網(wǎng)絡(luò)請(qǐng)求豈不是既浪費(fèi)了流量也浪費(fèi)了手機(jī)和服務(wù)器的性能?

那么此時(shí)有的同學(xué)就有問(wèn)題了。你就不能在Fragment顯示的時(shí)候去加載數(shù)據(jù)嗎?

問(wèn)的好!在解答之前我們先來(lái)看下Fragment的生命周期。

想必這張圖大家應(yīng)該都非常熟悉了。

當(dāng)Fragment被預(yù)加載的時(shí)候,此Fragment的生命周期會(huì)從onAttach執(zhí)行到onResume。顯然我們無(wú)法通過(guò)Fragment的生命周期來(lái)控制Fragment的延遲加載。

那么該怎么辦呢?我們且往下看。

2. 如何處理Fragment的延遲加載?

通過(guò)上一小節(jié)的分析我們知道想要在Fragment的生命周期中處理延遲加載的問(wèn)題顯然是走不通的。所以想要處理Fragment的延遲加載就需要另想它法了。

還好,在Fragment中為我們提供了一個(gè)?setUserVisibleHint(isVisibleToUser: Boolean)?的方法,這個(gè)方法中有一個(gè)?isVisibleToUser?的boolean類型的參數(shù),其意義表示當(dāng)前的Fragment是否對(duì)用戶可見(jiàn)。

因此,對(duì)于Fragment的延遲加載我們便可以通過(guò)這個(gè)方法來(lái)展開(kāi)。既然要使用setUserVisibleHint(isVisibleToUser: Boolean)那么就應(yīng)該知道這個(gè)方法的調(diào)用時(shí)機(jī)。我們寫一個(gè)ViewPager嵌套Fragment的例子來(lái)打印下日志:

注:上圖打印的日志中”position:0“表示當(dāng)前Fragment,“position:1”表示預(yù)加載的Fragment,下同。

可見(jiàn)該方法是在Fragment的onAttach之前就已經(jīng)被調(diào)用了。因此,對(duì)于延遲加載我們可以在setUserVisibleHint(isVisibleToUser: Boolean)方法及onViewCreated(view: View, savedInstanceState: Bundle?)添加標(biāo)志位來(lái)控制是否加載數(shù)據(jù)。我們來(lái)看下代碼:?

abstract class BaseLazyFragment : Fragment() { /** * 當(dāng)前Fragment狀態(tài)是否可見(jiàn) */ private var isVisibleToUser: Boolean = false /** * 是否已創(chuàng)建View */ private var isViewCreated: Boolean = false /** * 是否第一次加載數(shù)據(jù) */ private var isFirstLoad = true override fun setUserVisibleHint(isVisibleToUser: Boolean) { super.setUserVisibleHint(isVisibleToUser) this.isVisibleToUser = isVisibleToUser onLazyLoad() } private fun onLazyLoad() { if (isVisibleToUser && isViewCreated && isFirstLoad) { isFirstLoad = false lazyLoad() } } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) isViewCreated = true onLazyLoad() }????protected?abstract?fun?lazyLoad()}

我們通過(guò)在Fragment中添加了三個(gè)標(biāo)志位實(shí)現(xiàn)了延遲加載的功能。我們到TestFragment嘗試一下:

class?TestFragment?:?BaseLazyFragment()?{ private var position: Int = 0 override fun setUserVisibleHint(isVisibleToUser: Boolean) { super.setUserVisibleHint(isVisibleToUser) val bundle = arguments position = bundle!!.getInt(KEY_POSITION) } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { val cardView = CardView(inflater, container) cardView.bind(Card.fromBundle(arguments!!),position) return cardView.view } companion object { private const val KEY_POSITION = "position" fun getInstance(card: Card, position: Int): TestFragment { val fragment = TestFragment() val bundle = card.toBundle() bundle.putInt(KEY_POSITION, position) fragment.arguments = bundle return fragment } } override fun lazyLoad() { showToast("Fragment$position is loading data") } private fun showToast(content: String) { Toast.makeText(context, content, Toast.LENGTH_SHORT).show()????}}

我們來(lái)看下效果:

嗯!立竿見(jiàn)影,只有當(dāng)Fragment完全顯示出來(lái)的時(shí)候loading data的操作才被執(zhí)行。這種延遲加載的方案在Androidx 1.1.0版本以前被廣泛應(yīng)用。而在Androidx 1.1.0版本中,Google對(duì)于Fragment進(jìn)行了優(yōu)化處理,使得延遲加載也有了新的解決方案。

二、Fragment的setMaxLifecycle探究

上一節(jié)中我們講到因?yàn)閂iewPager的預(yù)加載機(jī)制以及Fragment的生命周期無(wú)法得以控制,我們不得不通過(guò) setUserVisibleHint(isVisibleToUser: Boolean) 和 onViewCreated(view: View, savedInstanceState: Bundle?) 方法以及添加三個(gè)標(biāo)志位來(lái)處理延遲加載,顯然這樣的代碼并不優(yōu)雅。

當(dāng)我們將Android項(xiàng)目遷移到Androidx 并將 Androidx 版本升級(jí)到1.1.0之后發(fā)現(xiàn),我們第一節(jié)中用到的setUserVisibleHint(isVisibleToUser: Boolean)方法已被標(biāo)記為廢棄了!

/** * ... 省略其它注釋 * @deprecated Use {@link FragmentTransaction#setMaxLifecycle(Fragment, Lifecycle.State)} * instead. */@Deprecatedpublic void setUserVisibleHint(boolean isVisibleToUser) { if (!mUserVisibleHint && isVisibleToUser && mState < STARTED && mFragmentManager != null && isAdded() && mIsCreated) { mFragmentManager.performPendingDeferredStart(this); } mUserVisibleHint = isVisibleToUser; mDeferStart = mState < STARTED && !isVisibleToUser; if (mSavedFragmentState != null) { // Ensure that if the user visible hint is set before the Fragment has // restored its state that we don't lose the new value mSavedUserVisibleHint = isVisibleToUser; }}

并且從注釋中可以看到使用 FragmentTransaction#setMaxLifecycle(Fragment, Lifecycle.State)?方法來(lái)替換setUserVisibleHint方法。setMaxLifecycle實(shí)在Androidx 1.1.0中新增加的一個(gè)方法。

setMaxLifecycle從名字上來(lái)看意思是設(shè)置一個(gè)最大的生命周期,因?yàn)檫@個(gè)方法是在 FragmentTransaction 中,因此我們可以知道應(yīng)該是為Fragment來(lái)設(shè)置一個(gè)最大的生命周期。我們來(lái)看下setMaxLifecycle的源碼:

/** * 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 */@NonNullpublic FragmentTransaction setMaxLifecycle(@NonNull Fragment fragment, @NonNull Lifecycle.State state) { addOp(new Op(OP_SET_MAX_LIFECYCLE, fragment, state)); return this;}

這個(gè)方法接收一個(gè)Fragment參數(shù)和一個(gè)Lifecycle的狀態(tài)參數(shù)。Lifecycle是Jetpack中很重要的一個(gè)庫(kù),它具有對(duì)Activity和Fragment生命周期感知能力,相信很多同學(xué)都應(yīng)該對(duì)Lifecycle都略知一二。

在Lifecycle的State中定義了五種生命周期狀態(tài),如下:

public enum State { /** * Destroyed state for a LifecycleOwner. After this event, this Lifecycle will not dispatch * any more events. For instance, for an {@link android.app.Activity}, this state is reached * right before Activity's {@link android.app.Activity#onDestroy() onDestroy} call. */ DESTROYED, /** * Initialized state for a LifecycleOwner. For an {@link android.app.Activity}, this is * the state when it is constructed but has not received * {@link android.app.Activity#onCreate(android.os.Bundle) onCreate} yet. */ INITIALIZED, /** * Created state for a LifecycleOwner. For an {@link android.app.Activity}, this state * is reached in two cases: * * after {@link android.app.Activity#onCreate(android.os.Bundle) onCreate} call; * right before {@link android.app.Activity#onStop() onStop} call. * */ CREATED, /** * Started state for a LifecycleOwner. For an {@link android.app.Activity}, this state * is reached in two cases: * * after {@link android.app.Activity#onStart() onStart} call; * right before {@link android.app.Activity#onPause() onPause} call. * */ STARTED, /** * Resumed state for a LifecycleOwner. For an {@link android.app.Activity}, this state * is reached after {@link android.app.Activity#onResume() onResume} is called. */ RESUMED; /** * Compares if this State is greater or equal to the given {@code state}. * * @param state State to compare with * @return true if this State is greater or equal to the given {@code state} */ public boolean isAtLeast(@NonNull State state) { return compareTo(state) >= 0; } }

而在?setMaxLifecycle?中接收的生命周期狀態(tài)要求不能低于?CREATED,否則會(huì)拋出一個(gè)?IllegalArgumentException?的異常。當(dāng)傳入?yún)?shù)為DESTROYED或者INITIALIZED時(shí)則會(huì)拋出如下圖的異常:

因此除去這兩個(gè)生命周期外,僅剩下CREATED、STARTED、RESUMED三個(gè)生命周期狀態(tài)的參數(shù)可用,那么接下來(lái)我們就逐個(gè)來(lái)研究這三個(gè)參數(shù)的效果。

1. 不設(shè)置setMaxLifecycle

我們先來(lái)看下在不設(shè)置setMaxLifecycle的時(shí)候添加一個(gè)Fragment的狀態(tài),以便和后邊的情況進(jìn)行對(duì)比。首先我們?cè)贏ctivity中添加一個(gè)Fragment,代碼如下:

fragment = TestLifecycleFragment.getInstance(Card.DECK[0], 0)val fragmentTransaction = supportFragmentManager.beginTransaction()fragmentTransaction.add(R.id.ll_fragment, fragment)fragmentTransaction.commit()

啟動(dòng)Activity,我們將該Fragment生命周期的日志打印出來(lái)如下:

可以看到這個(gè)Fragment生命周期從onAttach一直執(zhí)行到了onResume,?并且在Activity中成功顯示出了Fragment

2. setMaxLifecycle與CREATED

接下來(lái),我們將maxLifecycle設(shè)置為CREATED:

fragment = TestLifecycleFragment.getInstance(Card.DECK[0], 0)val fragmentTransaction = supportFragmentManager.beginTransaction()fragmentTransaction.add(R.id.ll_fragment, fragment)fragmentTransaction.setMaxLifecycle(fragment, Lifecycle.State.CREATED)fragmentTransaction.commit()

再來(lái)看日志輸出:

可以看到該Fragment的生命周期僅僅執(zhí)行到了onCreate就沒(méi)再往下執(zhí)行了。并且Activity中沒(méi)有加載出來(lái)當(dāng)前Fragment。

那么現(xiàn)在問(wèn)題來(lái)了,假設(shè)Fragment已經(jīng)執(zhí)行到了onResume, 此時(shí)再為Fragment設(shè)置一個(gè)CREATED的最大生命周期會(huì)出現(xiàn)什么樣的情況呢?我們通過(guò)日志來(lái)驗(yàn)證一下:

從日志中可以看到已經(jīng)執(zhí)行了onResume的Fragment,將其最大生命周期設(shè)置為CREATED后會(huì)執(zhí)行onPause->onStop->onDestoryView。也就是回退到了onCreate的狀態(tài)。

3. setMaxLifecycle與STARTED

接下來(lái),我們將maxLifecycle設(shè)置為STARTED:

fragment = TestLifecycleFragment.getInstance(Card.DECK[0], 0)val fragmentTransaction = supportFragmentManager.beginTransaction()fragmentTransaction.add(R.id.ll_fragment, fragment)fragmentTransaction.setMaxLifecycle(fragment, Lifecycle.State.STARTED)fragmentTransaction.commit()

日志輸出如下:

可以看到Fragment的生命周期執(zhí)行到了onStart,并且Activity中成功顯示出了當(dāng)前fragment。

同樣,假設(shè)Fragment已經(jīng)執(zhí)行到了onResume方法再為其設(shè)置最大生命周期為 STARTED 會(huì)怎樣呢?來(lái)看日志:

可以看到,設(shè)置最大生命周期STARTED后Fragment執(zhí)行了onPause方法,也就是生命周期退回到了onStart。

4. setMaxLifecycle與RESUMED

最后,我們將maxLifecycle設(shè)置為RESUMED:

fragment = TestLifecycleFragment.getInstance(Card.DECK[0], 0)val fragmentTransaction = supportFragmentManager.beginTransaction()fragmentTransaction.add(R.id.ll_fragment, fragment)fragmentTransaction.setMaxLifecycle(fragment, Lifecycle.State.RESUMED)fragmentTransaction.commit()

可以看到此時(shí)和第一種情況一樣的效果,Fragment的生命周期執(zhí)行到了 onResume。

而對(duì)于已經(jīng)執(zhí)行了onResume后的Fragment,再去設(shè)置最大生命周期為RESUMED會(huì)怎么樣呢?因?yàn)楫?dāng)前Fragment已經(jīng)是RESUMED狀態(tài)了,所以不會(huì)再去執(zhí)行任何代碼。

到這里我們可以得出一個(gè)結(jié)論:

通過(guò)setMaxLifecycle方法可以精確控制Fragment生命周期的狀態(tài),如果Fragment的生命周期狀態(tài)小于被設(shè)置的最大生命周期,則當(dāng)前Fragment的生命周期會(huì)執(zhí)行到被設(shè)置的最大生命周期;

反之,如果Fragment的生命周期狀態(tài)大于被設(shè)置的最大生命周期,那么則會(huì)回退到被設(shè)置的最大生命周期。

有了這一結(jié)論,在ViewPager中便可以對(duì)Fragment的生命周期進(jìn)行控制,以此來(lái)更方便的實(shí)現(xiàn)延遲加載功能了。

三、Fragment延遲加載的今生

1、延遲加載新方案之于ViewPager

通過(guò)上一小節(jié)的分析我們知道了可以通過(guò)setMaxLifecycle來(lái)設(shè)置Fragment的最大生命周期,從而可以實(shí)現(xiàn)ViewPager中Fragment的延遲加載。當(dāng)然,關(guān)于生命周期狀態(tài)處理的操作無(wú)需我們自己實(shí)現(xiàn),在Androidx 1.1.0版本中的FragmentStatePagerAdapter已經(jīng)幫我們實(shí)現(xiàn)了,只需要在使用時(shí)候傳進(jìn)去相應(yīng)的參數(shù)即可。

FragmentStatePagerAdapter的構(gòu)造方法接收兩個(gè)參數(shù),如下:

/** * Constructor for {@link FragmentStatePagerAdapter}. * * If {@link #BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT} is passed in, then only the current * Fragment is in the {@link Lifecycle.State#RESUMED} state, while all other fragments are * capped at {@link Lifecycle.State#STARTED}. If {@link #BEHAVIOR_SET_USER_VISIBLE_HINT} is * passed, all fragments are in the {@link Lifecycle.State#RESUMED} state and there will be * callbacks to {@link Fragment#setUserVisibleHint(boolean)}. * * @param fm fragment manager that will interact with this adapter * @param behavior determines if only current fragments are in a resumed state */public FragmentStatePagerAdapter(@NonNull FragmentManager fm, @Behavior int behavior) { mFragmentManager = fm; mBehavior = behavior;}

第一個(gè)FragmentManager 參數(shù)不必多說(shuō),第二個(gè)參數(shù)時(shí)一個(gè)枚舉類型的Behavior參數(shù),其可選值如下:

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

當(dāng)behavior為BEHAVIOR_SET_USER_VISIBLE_HINT時(shí),Fragment改變的時(shí)候,setUserVisibleHint方法會(huì)被調(diào)用,也就是這個(gè)參數(shù)其實(shí)是為了兼容以前的老代碼。并且BEHAVIOR_SET_USER_VISIBLE_HINT參數(shù)已經(jīng)被置為廢棄。所以我們的可選參數(shù)只剩下了BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT。

當(dāng)behavior為BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT時(shí)意味著只有當(dāng)前顯示的Fragment會(huì)被執(zhí)行到onResume,而其它Fragment的生命周期都只會(huì)執(zhí)行到onStart。

這一功能時(shí)如何實(shí)現(xiàn)的呢?我們追隨BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT的腳步找到了setPrimaryItem方法,這個(gè)方法的作用是設(shè)置ViewPager當(dāng)前顯示的Item,其源碼如下:

public void setPrimaryItem(@NonNull ViewGroup container, int position, @NonNull Object object) { Fragment fragment = (Fragment)object; 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.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; } }

這段代碼非常簡(jiǎn)單易懂,mCurrentPrimaryItem是當(dāng)前正在顯示的item,fragment是接下來(lái)要顯示的item。可以看到當(dāng)mBehavior 為BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT時(shí),mCurrentPrimaryItem的最大生命周期被設(shè)置為了STARTED,而fragment的最大生命周期則被設(shè)置為了RESUMED。

而當(dāng)mBehavior為BEHAVIOR_SET_USER_VISIBLE_HINT時(shí)仍然會(huì)調(diào)用setUserVisibleHint方法,這種情況就不再討論,因?yàn)锽EHAVIOR_SET_USER_VISIBLE_HINT也已經(jīng)被廢棄掉了。 那么我們著重來(lái)分析一下BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT時(shí)的情況:

mCurrentPrimaryItem是當(dāng)前顯示的Fragment,所以該Fragment必然已經(jīng)執(zhí)行到了onResume方法,而此時(shí)為其設(shè)置了最大生命周期STARTED,那么mCurrentPrimaryItem必然會(huì)執(zhí)行onPause退回到STARTED狀態(tài)。 而fragment當(dāng)前生命周期狀態(tài)為onStart,當(dāng)為其設(shè)置了RESUME的最大生命周期狀態(tài)后,fragment必然會(huì)執(zhí)行onResume方法進(jìn)入RESUMED狀態(tài)。

知道了這一結(jié)論后,我們?cè)偃ミM(jìn)行懶加載的控制是不是就異常簡(jiǎn)單了?此時(shí)我們只需要一個(gè)flag去標(biāo)志是否是第一次加載數(shù)據(jù)就可以了。

因此,懶加載的實(shí)現(xiàn)可以如下:

abstract class TestLifecycleFragment : Fragment() { private var isFirstLoad = true override fun onResume() { super.onResume() if (isFirstLoad) { isFirstLoad = false loadData() } } abstract fun loadData()}

2、延遲加載之于ViewPager2

(有機(jī)會(huì)專門分享一篇講解ViewPager2的文章。)在分析offScreenPageLimit時(shí)候得出過(guò)這樣一個(gè)結(jié)論:

ViewPager2的offScreenPageLimit默認(rèn)值為OFFSCREEN_PAGE_LIMIT_DEFAULT,當(dāng)setOffscreenPageLimit為OFFSCREEN_PAGE_LIMIT_DEFAULT時(shí)候會(huì)使用RecyclerView的緩存機(jī)制。

默認(rèn)只會(huì)加載當(dāng)前顯示的Fragment,而不會(huì)像ViewPager一樣至少預(yù)加載一個(gè)item。

當(dāng)切換到下一個(gè)item的時(shí)候,當(dāng)前Fragment會(huì)執(zhí)行onPause方法,而下一個(gè)Fragment則會(huì)從onCreate一直執(zhí)行到onResume。當(dāng)再次滑動(dòng)回第一個(gè)頁(yè)面的時(shí)候當(dāng)前頁(yè)面同樣會(huì)執(zhí)行onPuase,而第一個(gè)頁(yè)面會(huì)執(zhí)行onResume。

也就是說(shuō)在ViewPager2中,默認(rèn)關(guān)閉了預(yù)加載機(jī)制。沒(méi)有了預(yù)加載機(jī)制再談延遲加載其實(shí)也沒(méi)有任何意義了。所以關(guān)于ViewPager2的延遲加載也就不用多說(shuō)了吧?

只需要將網(wǎng)絡(luò)請(qǐng)求放到onStart中即可。相信隨著ViewPager2的普及延遲加載的概念也會(huì)慢慢淡出開(kāi)發(fā)者的視線。

2020/1/4補(bǔ)充:

如果為ViewPager2設(shè)置了offScreenPageLimit(1)那結(jié)果會(huì)是怎樣的呢?我們來(lái)看日志:

從日志中可以看到ViewPager2預(yù)加載了一個(gè)Fragment,并且預(yù)加載的Fragment的生命周期僅僅執(zhí)行到了onStart。所以此處我們可以猜測(cè)在FragmentStateAdapter中一定設(shè)置了setMaxLifecycle(fragment, STARTED),具體源碼不再貼出,大家可以自行查看。因此,此時(shí)處理懶加載問(wèn)題其實(shí)和ViewPager的懶加載新方案如出一轍了,僅僅需要添加一個(gè)boolean值即可。

三、總結(jié)

本篇文章對(duì)于Fragment的延遲加載進(jìn)行了深入的探究,并且了解了在Androidx 1.1.0版本中對(duì)Fragment最大生命周期狀態(tài)的控制,從而探究出了Fragment延遲加載的新方案。

對(duì)于ViewPager2,因其默認(rèn)不會(huì)進(jìn)行預(yù)加載因此也就意味著我們無(wú)需處理ViewPager2的延遲加載問(wèn)題。好了,這一篇花費(fèi)了我兩個(gè)周末(其實(shí)是上周末寫了一半偷了個(gè)懶)的文章到此就結(jié)束了,如果你從中學(xué)有所收獲那么請(qǐng)你不要吝嗇留下你的贊。

相關(guān)文章:

  • Retrofit 用了那么久,動(dòng)態(tài)代理還不明白

  • 2019年互聯(lián)網(wǎng)公司福利縮水指南

  • 再見(jiàn)2019!你好2020!

今日問(wèn)題:

Fragment用得溜嘛?

專屬升級(jí)社區(qū):《這件事情,我終于想明白了》?

總結(jié)

以上是生活随笔為你收集整理的判断当前界面是该fragment_学不动也要学!探究Fragment延迟加载的前世今生的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 午夜爱爱网站 | 欧美日韩一区二区三区国产精品成人 | 91美女片黄在线观看91美女 | 欧美色图亚洲视频 | 精品丰满少妇一区二区三区 | 日本免费在线视频观看 | 国产福利小视频在线观看 | 日韩精品电影 | 大尺度做爰呻吟舌吻网站 | 老色批av | 亚洲 精品 综合 精品 自拍 | 精品一区二区视频 | 欧美精品在线观看视频 | 国产亚洲精品aaaaaaa片 | 一区二区三区在线观看免费视频 | 五月天色综合 | 日韩成人在线播放 | 亚洲狼人伊人 | 欧美成人三级在线视频 | 色综合中文字幕 | 国产精品刘玥久久一区 | 91资源在线播放 | 成人永久视频 | 女人下边被添全过视频 | 午夜在线一区 | 亚洲天堂第一区 | 日韩高清不卡在线 | 国语对白真实视频播放 | 夜夜嗨aⅴ一区二区三区 | 18禁网站免费无遮挡无码中文 | 日韩无码精品一区二区三区 | 2024av视频| 91看大片 | 兔费看少妇性l交大片免费 日韩高清不卡 | 911久久| 欧美色xxxx| 嫩草影院懂你的 | 亚洲欧美中文字幕 | 特a级黄色片 | 欧美福利第一页 | 中文字幕一区二区三区乱码不卡 | 午夜视频福利 | 日韩中文在线观看 | 五个女闺蜜把我玩到尿失禁 | 欧美10p | 国产精品无码免费在线观看 | 女人扒开腿让男人桶爽 | 欧亚一级片 | 丰满少妇乱子伦精品看片 | 国产xxxxwwww | 999热| 91国产视频在线播放 | 国产精品乱码久久久久久 | 美女视频久久 | 嫩草影院在线免费观看 | 毛片在线免费视频 | 国产黄色大片 | 短视频在线观看 | 91福利网| 黄色aa视频 | 成人激情视频在线播放 | 91精品人妻一区二区三区果冻 | 亚洲国产日韩在线一区 | 三年大片在线观看 | 美女网站免费观看视频 | 久久免费影院 | 能免费看黄色的网站 | 久久久久亚洲av成人毛片韩 | 国产精品一区在线 | 欧美鲁| 激情视频亚洲 | 一区二区三区麻豆 | 男女免费看| 深夜福利影院 | 67194成人在线观看 | 国产成人无码AA精品区 | 日日碰狠狠添天天爽无码 | www.色欧美| 魔性诱惑 | 狠狠躁狠狠躁视频专区 | 国产精品极品 | a级片在线看 | 丝袜一区二区三区 | 大黑人交xxx极品hd | 337p粉嫩大胆色噜噜噜 | xxxx在线视频 | 黄色a级在线观看 | 免费的a级片 | 无码人妻丰满熟妇精品 | 精品人妻久久久久一区二区三区 | 黄色1级毛片 | 综合色站导航 | 公肉吊粗大爽色翁浪妇视频 | 国产高清视频免费在线观看 | 宿舍女女闺蜜调教羞辱 | 欧美性生活一区二区 | 182tv午夜福利在线观看 | 国产成人无码www免费视频播放 | 欧美一二三 |