看了網(wǎng)上很多Fragment懶加載的文章,自己實踐后總結(jié)一下:
在使用ViewPager裝載Fragment的時候一般會遇到椒丧,F(xiàn)ragment懶加載的問題壹甥。
因為系統(tǒng)默認(rèn)的ViewPager會緩存當(dāng)前頁面相鄰的兩個頁面,左右各一個壶熏,這兩個頁面在屏幕外句柠,在加載當(dāng)前頁面的時候,左右兩個頁面會同時加載久橙。
先看一下Fragment生命周期:
ViewPager
裝載3個Fragment1
俄占,Fragment2
,Fragment3
假設(shè)屏幕展示的是Fragment2
淆衷,當(dāng)切換到Fragment2
時,F(xiàn)ragment會回調(diào)生命周期中相應(yīng)的函數(shù):
Fragment1
: setUserVisibleHint(boolean isVisibleToUser)
--> onCreateView()
--> onActivityCreated()
Fragment2
: setUserVisibleHint(boolean isVisibleToUser)
--> onCreateView()
--> onActivityCreated()
Fragment3
: setUserVisibleHint(boolean isVisibleToUser)
--> onCreateView()
--> onActivityCreated()
當(dāng)前Fragment處于可見狀態(tài)的時候渤弛,setUserVisibleHint(boolean isVisibleToUser)
函數(shù)中的isVisibleToUser = true
當(dāng)前Fragment處于不可見祝拯,setUserVisibleHint(boolean isVisibleToUser)
函數(shù)中的isVisibleToUser = false
利用這個值得不同可以區(qū)分,進(jìn)而實現(xiàn)懶加載
代碼如下:
public class LazyLoadFragment extends Fragment {
protected boolean isViewInitiated;
protected boolean isVisibleToUser;
protected boolean isDataInitiated;
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
this.isVisibleToUser = isVisibleToUser;
//Fragment狀態(tài)改變的時候加載數(shù)據(jù)
prepareFetchData();
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
initVariable();
return super.onCreateView(inflater, container, savedInstanceState);
}
private void initVariable() {
isViewInitiated = false;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
isViewInitiated = true;
//Fragment狀態(tài)改變的時候加載數(shù)據(jù)
prepareFetchData();
}
public void prepareFetchData() {
if (isVisibleToUser && isViewInitiated && !isDataInitiated) {
isDataInitiated = true;
fetchData();
}
}
private void fetchData() {
//加載數(shù)據(jù),刷新View
}
}
注意幾個知識點:
剛被new出來的Fragment并沒有開始它的生命周期佳头,當(dāng)它被添加到FragmentManager時生命周期才開始鹰贵。
viewPager.setOffscreenPageLimit();該方法設(shè)置ViewPager允許有多少張pages存在于屏幕外(不包括正在顯示的page),默認(rèn)值是1康嘉。在范圍之外的pages 的View會被銷毀碉输,即onDestroyView()會被執(zhí)行。
-
Viewpager里面FragmentPagerAdapter亭珍、FragmentStatePagerAdapter的區(qū)別:
FragmentPagerAdapter會將每一個生成的Fragment都放到內(nèi)存中,即無論怎么滑動切換ViewPager阻荒,都不會有一個Fragment的onDestroy方法被調(diào)用众羡。但Fragment不在viewPager.setOffscreenPageLimit(3);保護(hù)的范圍內(nèi)會調(diào)用FragmentManager的detach()方法,相應(yīng)的Fragment的onDestroyView會執(zhí)行羊壹,但Fragment實例仍在齐婴!所以該類適用于需要展示的Fragment比較少的情況。
FragmentStateAdapter 有點類似于LIstview的RecyclerBin機制眨攘,當(dāng)Fragment不在viewPager.setOffscreenPageLimit(3);保護(hù)的范圍內(nèi)嚣州,F(xiàn)ragment的就會被銷毀,onDestroy()该肴、onDetach()方法會被執(zhí)行。適用于要展示Fragment數(shù)量比較多秦效,F(xiàn)ragment的子View和數(shù)據(jù)量復(fù)雜的情況涎嚼。