美文网首页
Viewpager和Fragment的懒加载机制

Viewpager和Fragment的懒加载机制

作者: Aaron大宝剑 | 来源:发表于2020-07-19 21:22 被阅读0次

    一、背景

    ViewPager默认加载当前页面,而且预加载当前页面的前后两个页面数据(即同时会加载3个页面的数据),如果3个页面都有网络请求,就会影响性能,影响用户体验,由此,懒加载就尤为重要了,可以在滑到哪个fragment的时候,该fragment再进行网络请求。

    二、懒加载

    所谓的懒加载,其实也就是延迟加载,就是等到该页面的UI展示给用户时,再加载该页面的数据(从网络、数据库等),而不是依靠ViewPager预加载机制提前加载两三个,甚至更多页面的数据.这样可以提高所属Activity的初始化速度,也可以为用户节省流量。

    三、懒加载方案

    1、通过ViewPager的setOffscreenPageLimit(int limit)

    private static final int DEFAULT_OFFSCREEN_PAGES = 1;
    ...
    public void setOffscreenPageLimit(int limit) {
            if (limit < DEFAULT_OFFSCREEN_PAGES) {
                Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to "
                        + DEFAULT_OFFSCREEN_PAGES);
                limit = DEFAULT_OFFSCREEN_PAGES;
            }
            if (limit != mOffscreenPageLimit) {
                mOffscreenPageLimit = limit;
                populate();
            }
        }
    

    该方法不可行,因为查看源码发现无论怎么设置,默认预加载页面数都是1,也就是说即使limit设置为0,最终还是默认为1。

    2、setUserVisibleHint(boolean isVisibleToUser)

    Fragment为我们提供了一个方法setUserVisibleHint(boolean isVisibleToUser),其中的参数isVisibleToUser就是表示该Fragment的UI对于用户是否可见。

    所以可以重写此方法,然后根据回调的isVisibleToUser参数来进行相关的逻辑判断,以达到懒加载的效果。如果isVisibleToUser为true的话表示当前Fragment对用户可见,此时再去加载页面数据。由于ViewPager内会装载多个Fragment,而这种懒加载机制对于各个Fragment属于共同操作,因此适合将其抽取到BaseFragment中.

    但是注意:

    setUserVisibleHint(boolean isVisibleToUser)方法会多次回调,而且可能会在onCreateView()方法执行完毕之前回调。如果isVisibleToUser为true,然后进行数据加载和控件数据填充,但是onCreateView()方法并未执行完毕,此时就会出现NullPointerException空指针异常.

    基于以上原因,进行数据懒加载的时机需要满足两个条件:

    • onCreateView()方法执行完毕

    • setUserVisibleHint(boolean isVisibleToUser)方法返回true

    所以在BaseFragment中用两个布尔型标记来记录这两个条件的状态.只有同时满足了,才能加载数据。

    四、懒加载的实现

    public abstract class BaseFragment extends Fragment {
        // 视图加载完成标志位
        private boolean isViewCreated;
        // 视图对用户可见标志位
        private boolean isVisible;
    
    
        @Nullable
        @Override
        public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
           return inflater.inflate(getFragmentView(), container, false);
        }
    
        @Override
        public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
            super.onViewCreated(view, savedInstanceState);
            // fragment视图加载完成,设置视图加载完成标志位
            isViewCreated = true;
            // 可以开启懒加载
            lazyLoad();
        }
    
        // 该方法是在onCreate方法之前调用的
        @Override
        public void setUserVisibleHint(boolean isVisibleToUser) {
            super.setUserVisibleHint(isVisibleToUser);
            if (isVisibleToUser){
                isVisible = true;
                lazyLoad();
            }else {
                isVisible = false;
            }
        }
    
        private void lazyLoad(){
            /**
             * 牢记懒加载的2个重要条件:
             * 1、fragment视图已经加载完成
             * 2、fragment视图对用户可见了
             *
             * 所以,根据2个标志位进行判断
             */
            if (isViewCreated && isVisible) {
                loadData();
                // 数据加载后重置标志位,避免重复加载
                isVisible = false;
                isViewCreated = false;
            }
        }
    
      
        @Override
        public void onDestroyView() {
            super.onDestroyView();
            // fragment视图销毁时也重置标志位
            isVisible = false;
            isViewCreated = false;
        }
    
        protected abstract void loadData();
        protected abstract int getFragmentView();
    }
    

    相关文章

      网友评论

          本文标题:Viewpager和Fragment的懒加载机制

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