github地址
一、簡介
?????玩過微信的都知道,微信用的是懶加載的模式,之所以使用懶加載是因為:當(dāng)使用viewpager+adapter作為應(yīng)用大的布局時,viewpager會通過setOffscreenPageLimit來設(shè)置預(yù)加載的項目,不設(shè)置setOffscreenPageLimit,則默認(rèn)為1(設(shè)置0無效,可以查看該方法源碼知道),也就是當(dāng)我們打開應(yīng)用看到的時候fragmentOne時,實際上其他fragment(例如fragmentSecond)也進行了加載,只不過沒有顯示出來罷了,但是這樣就造成了不必要的資源浪費(例如,fragmentSecond沒有顯示,但是卻進行了大量的網(wǎng)絡(luò)加載操作)。
在此先要說下一下幾個方法:
1.ViewPager中的setOffscreenPageLimit方法,設(shè)置預(yù)加載的頁面?zhèn)€數(shù),參數(shù)不能小于1因為默認(rèn)最小就是1。作用是:可以讓Fragment視圖不會被銷毀。
2.Fragment中的setUserVisibleHint方法,當(dāng)參數(shù)為true時對用戶可見,當(dāng)為false時對用戶不可見(這是懶加載的關(guān)鍵所在)
二、使用步驟
1、LazyFragment:
/**
* A simple {@link Fragment} subclass.
* "懶加載"的Fragment的基類
*/
public abstract class LazyFragment extends Fragment {
private View view;
private boolean needInit; //是否需要在onCreateView中初始化組件
private boolean hasLoad; //標(biāo)識是否已經(jīng)加載過
private boolean hasCreated; //是否為第一次加載數(shù)據(jù)
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
//展示 & 沒有加載過
if (isVisibleToUser && !hasLoad) {
//如果當(dāng)前Fragment向用戶展示且沒有加載過,進行下一步判斷
if (hasCreated) {
//如果onCreateView已經(jīng)被創(chuàng)建,此時進行加載
initView();
} else {
//如果Fragment沒有創(chuàng)建,那么設(shè)置標(biāo)記,在onCreateView中加載
needInit = true;
}
}
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
view = inflater.inflate(getLayoutId(), container, false);
if (needInit) {
//是否要初始化,后面頁不需要
initView();
needInit = false;
}
hasCreated = true;
return view;
}
private void initView() {
init(view);
hasLoad = true;
}
//獲取Fragment的布局文件
@LayoutRes
protected abstract int getLayoutId();
//包含初始化數(shù)據(jù)
protected abstract void init(View view);
}
2、所有Fragment子類繼承于LazyFragment
public class ShopCartFragment extends LazyFragment {
@Override
protected int getLayoutId() {
return R.layout.fragment_shop_cart;
}
//初始化View和數(shù)據(jù)
@Override
protected void init(View view) {
//初始化View
initView();
//初始化數(shù)據(jù)
initData();
}
3、Activity中注意
//設(shè)置預(yù)加載頁面的數(shù)目,避免當(dāng)頁面?zhèn)€數(shù) > 3時,有Fragment被銷毀的情況
viewPager.setOffscreenPageLimit(mList.size() - 1);
4、另一個懶加載的Fragment的基類
public abstract class BaseFragment extends Fragment {
private boolean isVisible = false;//當(dāng)前Fragment是否可見
private boolean isInitView = false;//是否與View建立起映射關(guān)系
private boolean isFirstLoad = true;//是否是第一次加載數(shù)據(jù)
private View convertView;
private SparseArray<View> mViews;
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
LogUtil.m("isVisibleToUser " + isVisibleToUser + " " + this.getClass().getSimpleName());
if (isVisibleToUser) {
isVisible = true;
lazyLoadData();
} else {
isVisible = false;
}
super.setUserVisibleHint(isVisibleToUser);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
LogUtil.m(" " + this.getClass().getSimpleName());
convertView = inflater.inflate(getLayoutId(), container, false);
mViews = new SparseArray<>();
initView();
isInitView = true;
lazyLoadData();
return convertView;
}
private void lazyLoadData() {
if (isFirstLoad) {
LogUtil.m("第一次加載 " + " isInitView " + isInitView + " isVisible " + isVisible + " " + this.getClass().getSimpleName());
} else {
LogUtil.m("不是第一次加載" + " isInitView " + isInitView + " isVisible " + isVisible + " " + this.getClass().getSimpleName());
}
if (!isFirstLoad || !isVisible || !isInitView) {
LogUtil.m("不加載" + " " + this.getClass().getSimpleName());
return;
}
LogUtil.m("完成數(shù)據(jù)第一次加載"+ " " + this.getClass().getSimpleName());
initData();
isFirstLoad = false;
}
/**
* 加載頁面布局文件
* @return
*/
protected abstract int getLayoutId();
/**
* 讓布局中的view與fragment中的變量建立起映射
*/
protected abstract void initView();
/**
* 加載要顯示的數(shù)據(jù)
*/
protected abstract void initData();
/**
* fragment中可以通過這個方法直接找到需要的view,而不需要進行類型強轉(zhuǎn)
* @param viewId
* @param <E>
* @return
*/
protected <E extends View> E findView(int viewId) {
if (convertView != null) {
E view = (E) mViews.get(viewId);
if (view == null) {
view = (E) convertView.findViewById(viewId);
mViews.put(viewId, view);
}
return view;
}
return null;
}
}