ListView与RecyclerView的卡顿优化

本文讲解的主要是通过预处理布局来解决ListView和RecyclerView的卡顿问题。

ListView与RecyclerView的卡顿我将之分为两个阶段:

1)  绑定数据阶段  

这个阶段优化网上有很多说法,也已经被大家所熟知。 比如: 图片通过框架延迟加载,懒加载;  禁止在这里做耗时操作, 如: findViewById ,  创建对象, 处理业务逻辑, 处理复杂的计算逻辑等; 

2) 初始化layout阶段 

本文重点介绍的是这个阶段的优化, 有人会问, ListView通过viewHolder 通过判定convertView == null  这个不是固化的操作吗, 还有啥优化空间? 还能避免这一步??? RecyclerView 也是一样。 

答案当然是否定的。 是的, 我们不能避免这些固化的写法, 不能避免不去创建inflate layout .  那这个阶段还有啥可以优化的呢??? 

首先我要提出问题所在: 在ListView和RecyclerView被加载出来显示之后, 再滑动会出现卡顿, 而后就顺畅多了, 问题是显示之后, 在滑动为啥会卡顿呢 ??

RecyclerView 虽然比ListView灵活的多, 但是滚动时的卡顿确比ListView更明显, 有些人有疑问 :这难道不是绑定数据造成的吗?  其实不然。 是在滚动时会额外通过getView或者onCreateViewHolder  里面继续inflate.layout造成的。 很多有又有疑问, 为啥我没有这个感觉呢?? 那是因为很多layout不复杂的情况下效果很轻微, 但是如果你设置了header, 第一屏幕显示的都是header view , 而list是从第2页屏幕开始显示的呢??? 你有试过吗, 如果试过或者知道它们的缓存原理就会发现, 再RecyclerView或者ListView被显示出来的时候, getView或者onCreateViewHolder 并没有被执行, 或者执行很少, 只有在滚动时才获取执行, 然后就造成了卡顿。 那是因为它们的缓存机制导致, 初始化只加载可视范围内的item (这里不细细谈到它们的缓存机制,如果需要验证, 那么请在getView 或者onCreateViewHolder 哪里添加打印) 。 而滚动时inflate.layout  如果不复杂可能10ms就解决了, 你还能流程的体验, 但是如果复杂, 那么就会体验到滚动开始有轻微的卡顿(丢帧) , 知道它们的缓存机制完全足以支撑你的滚动, 不再去重新inflate.layout 。 

说了这么多, 没有解决办法, 然并卵 ? 

ListView 的预处理加载item , 也就是让它多加载几个item , 使之滚动的时候, 不去创建layout , 而是使用缓存好的item 。 

Method method = ShareReflectUtil.findMethod(this,”addViewBelow”,View.class, int.class);

intposition = getLastVisiblePosition();

View view = getChildAt(position);

for(inti =0;i < size;i++) {

       method.invoke(this,view,i + position);

}

RecyclerView的处理办法: 

RecyclerView.RecycledViewPool pool = recyclerView.getRecycledViewPool();

pool.setMaxRecycledViews(viewType,count);

for(intindex =0;index < count;index++) {

      pool.putRecycledView(recyclerView.getAdapter().createViewHolder(recyclerView,0));

}

注意一定要在setAdapter之后调用, 否者无效, 因为setAdapter时会清除你的pool缓存。

    原文作者:月下眠
    原文地址: https://www.jianshu.com/p/f7c80a3a536c
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞