存在的問題
- 默認(rèn)情況下,ViewPager會自動預(yù)加載
- 切換過程中會銷毀fragment視圖
下面的圖說明情況

如圖,在Activity中使用ViewPager嵌套三個Fragment,當(dāng)fragment1出現(xiàn)的時候,此時會預(yù)加載fragment2,滑動到fragment2會預(yù)加載fragment3,但是滑動到fragment3,此時會調(diào)用fragment1的destroyview方法,銷毀視圖。當(dāng)重新滑動到fragment1才會重新調(diào)用fragment1的oncreateview方法。注意此時并不會銷毀實例,不會調(diào)用ondestroy方法。
這樣就存在兩個問題
1、pagerview頻繁切換,導(dǎo)致fragment1.fragment3在頻繁的調(diào)用destroyview和oncreateview方法,重新創(chuàng)建視圖。這樣也浪費了大量的資源,用戶體驗不佳,雖然內(nèi)存消耗比較低
2、因為切換到fragment1的時候,同時預(yù)加載了fragment2,如果此時fragment2也有大量的耗時網(wǎng)絡(luò)請求要做,如果應(yīng)用對啟動反應(yīng)速度比較敏感,所以此時做了多余的工作?;蛘哒ffragment2也會顯示加載進度,顯然不符合我們的預(yù)期,能否把這些耗時的工作延遲加載,也是個問題
防止頻繁的銷毀視圖的解決方案
1、setOffscreenPageLimit(2)
2、或者重寫PagerAdaper的destroyItem方法為空即可
筆者此處使用的是方案2
public class MyViewPagerAdapter extends FragmentPagerAdapter {
...
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
//如果注釋這行,那么不管怎么切換,page都不會被銷毀
//super.destroyItem(container, position, object);
}
}
取消預(yù)加載解決方案
介紹兩個方法void setUserVisibleHint(boolean isVisibleToUser)、boolean getUserVisibleHint(),它們分別用作設(shè)置/獲得Fragment可見狀態(tài),我們可以重寫Fragment在其中做判斷。
第一步:重寫Fragment
public abstract class BaseFragment extends Fragment{
/** Fragment當(dāng)前狀態(tài)是否可見 */
protected boolean isVisible;
public void onCreate(android.os.Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(getUserVisibleHint()) {
isVisible = true;
onVisible();
} else {
isVisible = false;
onInvisible();
}
}
/**
* 可見
*/
protected void onVisible() {
lazyLoad();
}
/**
* 不可見
*/
protected void onInvisible() {
}
/**
* 延遲加載
* 子類必須重寫此方法
*/
protected abstract void lazyLoad();
}
第二步:繼承BaseFragment
1、聲明二個重要的變量
private boolean mHasLoadedOnce = false;
private boolean isPrepared = false;
2、onCreateView中進行控件初始化,初始化完成后加載數(shù)據(jù)
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_layuot2, null);
Dbug.d("","Fragment2==onCreateView");
initData();
isPrepared = true;
lazyLoad();
return view;
}
此處為什么要用isPrepared呢,因為lazyLoad();方法調(diào)用的時候控件可能沒初始化完成,會報空指針錯誤。
3、lazyLoad中判斷是否是首次加載和初始化完成
@Override
protected void lazyLoad() {
if (mHasLoadedOnce || !isPrepared)
return;
mHasLoadedOnce = true;
}
4、onDestroyView中變量重置
@Override
public void onDestroyView() {
super.onDestroyView();
Dbug.d("","Fragment2==onDestroyView");
mHasLoadedOnce = false;
isPrepared = false;
}