Fragment懒加载

github地址

https://github.com/zhouxu88/LazyFragment.git

一、简介

     玩过微信的都知道,微信用的是懒加载的模式,之所以使用懒加载是因为:当使用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;
    }

}

你可能感兴趣的:(Fragment懒加载)