美文网首页
Fragment 懒加载

Fragment 懒加载

作者: zarra1993 | 来源:发表于2017-02-21 16:09 被阅读0次

    Android 开发中,经常使用到 ViewPager + Fragment 的组合实现多页面的的数据展示。为了保证滑动流畅,ViewPager 引入了预加载机制;ViewPager 通过setOffscreenPageLimt(int limit) 方法来设置预加载页面的数量。
    void setOffscreenPageLimt(int limit)

    • 官方文档描述该方法将会设置当前页面的两边各自预加载的数量;并且超出这个数量的页面将会被重新创建,最终创建的数量为 2*limit+1
    • 该方法是一个可优化的项;如果我们提前知道展示的 pager 的数量,并且在 Pager 中加入了懒加载机制,调整这个设置保证了分页动画和交互的流畅。如果我们要展示的页面只有3-4 页,我们可以一次性将他们都缓存,这样当用户来回滑动的时候,布局的时间将会大大减少;
    • 如果页面布局比较复杂,将 limit 的值尽量设低;默认值为 1, 即便我们将 limit的值设为0 ,它也会被赋为 1,查看源码可知;
      但是如果我们的页面有大量的网络请求,特别是预加载多个页面的情况下,就会产生问题:
    • 并发请求造成堵塞,在网络不良的情况下,无限loading.....
    • 一般来说一个网络请求都会用使用到一个异步线程,大量的线程创建、运行、销毁又造成了系统资源的浪费;

    因此在预加载的过程中 ,最好先初始化 View,当滑动到对应的页面在执行网络请求布局;为了实现上述的需求,需要借用到 Fragment 的 setUserVisibleHint(boolean isVisibleToUser)

    void setUserVisibleHint(boolean isVisibleToUser)

    • 告诉系统当前 Fragment 是否对用户可见,默认值为 true , 并且在 Fragment 生命周期内都不会改变;
    • 当Fragment 不可见时,应用程序可能将该值设置为 false。系统可以用它来优化操作;
    • 该方法优先Fragment 的生命周期调用;而且对生命周期方法的调用不会产生影响;
      下面是实现懒加载的基类 BaseFragment
        public abstract class BaseFragment extends Fragment {
          View view;
          protected boolean isPrepared = false;//布局是否加载完毕
          protected boolean isVisible = false;//Fragment是否可见
          protected boolean isDataInitd = false;
          @Override
          public void setUserVisibleHint(boolean isVisibleToUser) {
                super.setUserVisibleHint(isVisibleToUser);
                System.out.println(this.getClass().getName()+"---isVisibleToUser "+isVisibleToUser);
                if(getUserVisibleHint()) {
                      System.out.println(this.getClass().getName()+"---onVisible");
                      isVisible =true;
                      onVisible();
                } else {
                      System.out.println(this.getClass().getName()+"---onInvisible");
                      isVisible = false;
                      onInvisible();
                }
          }
          private void onInvisible() {
          }
          private void onVisible() {
                lazyLoad();
          }
          protected abstract void getData();
          protected void lazyLoad() {
                System.out.println(this.getClass().getName()+"---lazyLoad() ");
                System.out.println(this.getClass().getName()+"---isPrepared " +isPrepared);
                System.out.println(this.getClass().getName()+"---isVisible " +isVisible);
                System.out.println(this.getClass().getName()+"---isDataInited " +isDataInitd);
    
                if(!isPrepared || !isVisible || isDataInitd) {
                      System.out.println(this.getClass().getName()+"---我没准备好");
                      return;
                } else {
                      isDataInitd = true;
                      System.out.println(this.getClass().getName()+"---执行网络请求");
                      getData();
                }
          }
    }
    

    下面是继承自BaseFragment 的 AFragment;

    public class AFramgent extends BaseFragment {
          View view;
          @Nullable
          @Override
          public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
                super.onCreateView(inflater,container,savedInstanceState);
                if(view == null) {
                view = inflater.inflate(R.layout.a_layout,container,false);
                isPrepared = true;
                lazyLoad();//第一个可见Fragment 需要调用LazyLoad();其他不用;
                }
                return view;
          }
           @Override
            protected void getData() {
                  System.out.println(this.getClass().getName()+"---getData " );
            }
    }
    

    使用过程中,由于 setUserVisibleHint() 要先于Fragment 的生命周期方法执行,所以要对第一个可见Fragment 做特殊处理,它的网络请求发生在 OnCreateView ()的 LazyLoad() 中,而其他的 Fragment 网络请求发生在调用setUserVisibleHint()中;具体调用如下

    2017-02-21_155202.png

    相关文章

      网友评论

          本文标题:Fragment 懒加载

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