github地址

一、简介

玩过微信的都知道,微信用的是懒加载的模式,之所以使用懒加载是因为:当使用viewpager+adapter作为应用大的布局时,viewpager会通过setOffscreenPageLimit来设置预加载的项目,不设置setOffscreenPageLimit,则默认为1(设置0无效,可以查看该方法源码知道),也就是当我们打开应用看到的时候fragmentOne时,实际上其他fragment(例如fragmentSecond)也进行了加载,只不过没有显示出来罢了,但是这样就造成了不必要的资源浪费(例如,fragmentSecond没有显示,但是却进行了大量的网络加载操作)。

在此先要说下一下几个方法:

1.ViewPager中的setOffscreenPageLimit方法,设置预加载的页面个数,参数不能小于1因为默认最小就是1。作用是:可以让Fragment视图不会被销毁。

2.Fragment中的setUserVisibleHint方法,当参数为true时对用户可见,当为false时对用户不可见(这是懒加载的关键所在)

二、使用步骤

1、LazyFragment:

/**

* A simple {@link Fragment} subclass.

* "懒加载"的Fragment的基类

*/

public abstract class LazyFragment extends Fragment {

private View view;

private boolean needInit; //是否需要在onCreateView中初始化组件

private boolean hasLoad; //标识是否已经加载过

private boolean hasCreated; //是否为第一次加载数据

@Override

public void setUserVisibleHint(boolean isVisibleToUser) {

super.setUserVisibleHint(isVisibleToUser);

//展示 & 没有加载过

if (isVisibleToUser && !hasLoad) {

//如果当前Fragment向用户展示且没有加载过,进行下一步判断

if (hasCreated) {

//如果onCreateView已经被创建,此时进行加载

initView();

} else {

//如果Fragment没有创建,那么设置标记,在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();

//包含初始化数据

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和数据

@Override

protected void init(View view) {

//初始化View

initView();

//初始化数据

initData();

}

3、Activity中注意

//设置预加载页面的数目,避免当页面个数 > 3时,有Fragment被销毁的情况

viewPager.setOffscreenPageLimit(mList.size() - 1);

4、另一个懒加载的Fragment的基类

public abstract class BaseFragment extends Fragment {

private boolean isVisible = false;//当前Fragment是否可见

private boolean isInitView = false;//是否与View建立起映射关系

private boolean isFirstLoad = true;//是否是第一次加载数据

private View convertView;

private SparseArray 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("完成数据第一次加载"+ " " + this.getClass().getSimpleName());

initData();

isFirstLoad = false;

}

/**

* 加载页面布局文件

* @return

*/

protected abstract int getLayoutId();

/**

* 让布局中的view与fragment中的变量建立起映射

*/

protected abstract void initView();

/**

* 加载要显示的数据

*/

protected abstract void initData();

/**

* fragment中可以通过这个方法直接找到需要的view,而不需要进行类型强转

* @param viewId

* @param

* @return

*/

protected 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;

}

}

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐