Fragment懒加载

作者: 唠嗑008 | 来源:发表于2017-01-11 22:57 被阅读152次

    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<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("完成数据第一次加载"+ "   " + 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 <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;
        }
    
    }
    
    

    相关文章

      网友评论

      • 大白栈:这两种有什么区别啊
        唠嗑008:@白痴狒狒 都可以实现的,这种东西只是实现的逻辑上有一点不一样而已

      本文标题:Fragment懒加载

      本文链接:https://www.haomeiwen.com/subject/llorbttx.html