美文网首页安卓精选案例常见问题解决
ViewPager+TabLayout+Fragment懒加载机

ViewPager+TabLayout+Fragment懒加载机

作者: Ruheng | 来源:发表于2017-03-03 10:52 被阅读9284次

    在Fragment和ViewPager配合使用的时候,ViewPager会使用预加载机制,使得我们在没有跳转到对应页面时,可能已经加载好了,这是个非常不好的用户体验,浪费用户的流量。本篇文章主要讲解在ViewPager+TabLayout+Fragment的情况下,Fragment的懒加载机制的实现以及项目封装情况。

    一、setUserVisibleHint(boolean isVisibleToUser)

    setUserVisibleHint(boolean isVisibleToUser)是Fragment中的一个回调函数。当前Fragment可见时,setUserVisibleHint()回调,其中isVisibleToUser=true。当前Fragment由可见到不可见或实例化时,setUserVisibleHint()回调,其中isVisibleToUser=false。

    setUserVisibleHint(boolean isVisibleToUser)调用时机

    ①在Fragment实例化,即在ViewPager中,由于ViewPager默认会预加载左右两个页面。此时预加载页面回调的生命周期流程:setUserVisibleHint() -->onAttach() --> onCreate()-->onCreateView()--> onActivityCreate() --> onStart() --> onResume()

    此时,setUserVisibleHint() 中的参数为false,因为不可见。

    ②在Fragmetn可见时,即ViewPager中滑动到当前页面时,因为已经预加载过了,之前生命周期已经走到onResume() ,所以现在**只会回调:setUserVisibleHint() **。

    此时,setUserVisibleHint() 中的参数为true,因为可见。

    ③在Fragment由可见变为不可见,即ViewPager由当前页面滑动到另一个页面,因为还要保持当前页面的预加载过程,所以只会回调:setUserVisibleHint()

    此时,setUserVisibleHint() 中的参数为false,因为不可见。

    ④由TabLayout直接跳转到一个未预加载的页面,此时生命周期的回调过程:setUserVisibleHint() -->setUserVisibleHint() -->onAttach() --> onCreate()-->onCreateView()--> onActivityCreate() --> onStart()
    --> onResume()

    回调了两次setUserVisibleHint() ,一次代表初始化时,传入参数是false,一次代表可见时,传入参数是true。这种情况比较特殊。

    总结:无论何时,setUserVisibleHint()都是先于其他生命周期的调用,并且初始化时调用,可见时调用,由可见转换成不可见时调用,一共三次时机。

    二、封装实现懒加载机制

    加载网络的情况:
    ①setUserVisibleHint()中参数为true,即Fragment可见;

    ②onCreateView()方法调用完毕,返回rootView,防止造成空指针问题;

    ③第一次调用网络加载,之前没加载过,即isFirst = false(有些别扭,可以改成true,对应代码做下修改)。

    满足以上条件,加载网络请求。

    取消加载网络的情况:

    ①setUserVisibleHint()中参数由true变为false,即Fragment由可见变为不可见;

    ②不是第一次调用网络加载,之前加载过,即isFirst = true。

    满足以上两者条件(只满足第一点也可以),取消网络请求。

    封装代码

    在BaseFragment中进行封装

    其中isFragment表示当前Fragment的可见情况
    isFirst表示是否已经加载过
    onFragmentVisibleChange()是一个可继承的空方法,子类实现,传入true,代表加载网络,传入false,代表取消网络加载。

     @Override
        public void setUserVisibleHint(boolean isVisibleToUser) {
            super.setUserVisibleHint(isVisibleToUser);
            if (isVisibleToUser) {
                isFragmentVisible = true;
            }
            if (rootView == null) {
                return;
            }
            //可见,并且没有加载过
            if (!isFirst&&isFragmentVisible) {
                onFragmentVisibleChange(true);
                return;
            }
            //由可见——>不可见 已经加载过
            if (isFragmentVisible) {
                onFragmentVisibleChange(false);
                isFragmentVisible = false;
            }
        }
    
        protected void onFragmentVisibleChange(boolean isVisible) {
    
        }
    

    其中有一种特殊情况不能满足上述代码中的条件进行网络加载。

    特殊情况:当TabLayout跳转到一个没有预加载过的Fragment,连续调用两次setUserVisibleHint方法,但此时rootView为空,不能进行加载。需要在onCreateView()方法最后判断是否进行网络加载,然后调用onFragmentVisibleChange(true)方法

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
         .................
            //可见,但是并没有加载过
            if (isFragmentVisible && !isFirst) {
                onFragmentVisibleChange(true);
            }
            return rootView;
        }
    

    子类实现的实例:

    @Override
        protected void onFragmentVisibleChange(boolean isVisible) {
            if(isVisible){
                //可见,并且是第一次加载
                mPresenter.requestPhotoList(SIZE,mStartPage);
                LoadingDialog.showDialogForLoading(getActivity());
            }else{
                //取消加载
                RxDisposeManager.get().cancel("photoList");
                LoadingDialog.cancelDialogForLoading();
            }
        }
    

    三、效果实现


    上图效果可以看出实现了懒加载,并且再次滑动回对应Fragment,也不会加载,通过下拉刷新才能更新数据,减少流量的耗费。


    上图效果可以看出,当TabLayout直接跳转到没有预加载的页面,也可以实现懒加载,效果一样。

    小伙伴们有没有很心动,下面有源码,欢迎参考使用!

    源码地址

    只需要看BaseFragment部分即可

    相关文章

      网友评论

      • 孔雀叔:感觉写的好乱,看的不明白
      • 91abcd89eccc:求android.support.design.jar包
      • 9df2a6e99159:我想问下两种情况,1,是不是只加载当前可见页面,前后相邻两个页面不会加载;2,已加载过的页面,滑动回来的时候时候仍在且不用重新加载
      • 英勇青铜5:来看下妹纸😂😂😂
      • kaxi4it:讲真,用户体验这个词,真的是被你们说烂了。划重点!!懒加载是个反用户体验的事情
        98442bffa4c1:不用懒加载导致半天加载不出来才是反用户体验吧
      • ziabo_yu:首先说一句,我这个评论不针对代码部分,建议不要在文章开头写这么多文字,特别是英文多的,建议可以先放一个效果图,然后再解释这种现象的由来,这样的话大家是不是更容易接受?
        super甜:个人觉得写得挺好的
      • catTom123:没有可行性
        Ruheng:@catTom123 具体是指什么意思呢?个人能力有限看不出
      • 随着地球转的人:妹子,你第一段就写错了,估计是笔误,技术文章发之前一定要自己先好好读一遍啊
        Ruheng:@浪客小旋风 老眼昏花了。现在改过来了
        随着地球转的人:@Ruheng 当前Fragment可见时,setUserVisibleHint()回调,其中isVisibleToUser=true。当前Fragment可见时,setUserVisibleHint()回调,其中isVisibleToUser=false。自己能看懂嘛
        Ruheng:@浪客小旋风 谢谢,已修改。还有我不是妹子
      • 南柯梦夏:我只是看下妹子
      • Android之路:onCreateActivity应该是onActivityCreate()吧
        Ruheng: @Android之路 应该是的,没注意。稍后改回来。谢谢

      本文标题:ViewPager+TabLayout+Fragment懒加载机

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