Android RecyclerView 优化处理
01.RecyclerView滑动卡顿
- RecyclerView滑动卡顿的原因有哪些?
- 第一种:嵌套布局滑动冲突
- 导致嵌套滑动难处理的关键原因在于当子控件消费了事件, 那么父控件就不会再有机会处理这个事件了, 所以一旦内部的滑动控件消费了滑动操作, 外部的滑动控件就再也没机会响应这个滑动操作了
- 第二种:嵌套布局层次太深,比如六七层等
- 测量,绘制布局可能会导致滑动卡顿
- 第三种:比如用RecyclerView实现画廊,加载比较大的图片,如果快速滑动,则可能会出现卡顿,主要是加载图片需要时间
- 第四种:在onCreateViewHolder或者在onBindViewHolder中做了耗时的操作导致卡顿。按stackoverflow上面比较通俗的解释:RecyclerView.Adapter里面的onCreateViewHolder()方法和onBindViewHolder()方法对时间都非常敏感。类似I/O读写,Bitmap解码一类的耗时操作,最好不要在它们里面进行。
- 第一种:嵌套布局滑动冲突
04.瀑布流图片错乱问题解决
05.item点击事件放在哪里优化
关于rv设置item条目点击事件有两种方式:1.在onCreateViewHolder中写;2.在onBindViewHolder中写;3.在ViewHolder中写。那么究竟是哪一种好呢?
1.在onCreateViewHolder中写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
final View view = LayoutInflater.from(mContext).inflate(R.layout.item_me_gv_grid, parent, false);
final MyViewHolder holder = new MyViewHolder(view);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (listener != null) {
listener.onItemClick(view, holder.getLayoutPosition());
}
}
});
return holder;
}2.在onBindViewHolder中写
1
2
3
4
5
6
7
8
9
10
11@Override
public void onBindViewHolder(@NonNull final MyViewHolder holder, int position) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (listener != null) {
listener.onItemClick(holder.itemView, holder.getAdapterPosition());
}
}
});
}3.在ViewHolder中写
1
2
3
4
5
6
7
8
9
10
11
12
13class MyViewHolder extends RecyclerView.ViewHolder {
MyViewHolder(final View itemView) {
super(itemView);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (listener != null) {
listener.onItemClick(itemView, getAdapterPosition());
}
}
});
}
}
onBindViewHolder() 中频繁创建新的 onClickListener 实例没有必要,建议实际开发中应该在 onCreateViewHolder() 中每次为新建的 View 设置一次就行。
08.拖拽排序与滑动删除优化
- 拖拽效果优化
- 在item被拖拽或侧滑时修改背景色,当动作结束后将背景色恢复回来,而ItemTouchHelper.Callback中正好有对应这两个状态的方法,分别是:onSelectedChanged()、clearView()。那么优化处理其实可以放到这两个方法中处理。
- 左右滑动使item透明度变浅且缩小该如何实现呢?让item执行了两种属性动画而已,在ItemTouchHelper.Callback中有一个方法可以拿到item被拖拽或滑动时的位移变化,那就是onChildDraw()方法,在该方法中设置item渐变和缩放属性动画。
- 出现问题,按照上面做法会出现删除后有空白item留出来,那么为什么会出现这种情况呢?并不是多出了两条空白数据,它们是正常的数据,只是看不到了,这是因为RecyclerView条目(itemView)覆用导致的,前面在onChildDraw()方法中对itemView设置了透明和缩小,而一个列表中固定只有几个itemView而已,当那两个透明缩小的itemView被再次使用时,之前设置的透明度和高度比例已经是0,所以就出现了这种情况,解决方法也很简单,只要在item被移除后,将itemView的透明度和高度比例设置回来即可。
09.暂停或停止加载数据优化
问题
- 比如用RecyclerView实现画廊,加载比较大的图片,如果快速滑动,则可能会出现卡顿,主要是加载图片需要时间
如何解决RecyclerView实现画廊卡顿?
- RecyclerView 滑动时不让 Glide 加载图片。滚动停止后才开始恢复加载图片。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16//RecyclerView.SCROLL_STATE_IDLE //空闲状态
//RecyclerView.SCROLL_STATE_FLING //滚动状态
//RecyclerView.SCROLL_STATE_TOUCH_SCROLL //触摸后状态
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
LoggerUtils.e("initRecyclerView"+ "恢复Glide加载图片");
Glide.with(ImageBrowseActivity.this).resumeRequests();
}else {
LoggerUtils.e("initRecyclerView"+"禁止Glide加载图片");
Glide.with(ImageBrowseActivity.this).pauseRequests();
}
}
});
14.recyclerView优化
14.1 DiffUtil刷新优化
- 分页拉取远端数据,对拉取下来的远端数据进行缓存,提升二次加载速度;对于新增或者删除数据通过 DiffUtil 来进行局部刷新数据,而不是一味地全局刷新数据。
14.2 布局优化
- 减少 xml 文件 inflate 时间
- 这里的 xml 文件不仅包括 layout 的 xml,还包括 drawable 的 xml,xml 文件 inflate 出 ItemView 是通过耗时的 IO 操作,尤其当 Item 的复用几率很低的情况下,随着 Type 的增多,这种 inflate 带来的损耗是相当大的,此时我们可以用代码去生成布局,即 new View() 的方式,只要搞清楚 xml 中每个节点的属性对应的 API 即可。
- 减少 View 对象的创建
- 一个稍微复杂的 Item 会包含大量的 View,而大量的 View 的创建也会消耗大量时间,所以要尽可能简化 ItemView;设计 ItemType 时,对多 ViewType 能够共用的部分尽量设计成自定义 View,减少 View 的构造和嵌套。
14.3 对itemView中孩子View的点击事件优化
- 对于每个ViewHolder都要设置子View点击监听器怎么办?
- 全局new一个Listener,通过view.getId与view.getTag取到对应View的id和数据,避免对每个新创建的ViewHolder都new出一个监听器,优化了对象的频繁创建带来的资源消耗。
14.4 复用RecycledViewPool
- 如果RecycledView的adapter是一样的话可以考虑共享一个对象池。 比如说:RecycledView嵌套RecycledView,里面的RecycledView大部分都adapter都一样。
- 具体该怎么封装???
14.5 RecyclerView预加载优化
14.6 RecyclerView嵌套滑动卡顿优化
- RecycleView与NestedScrollView的嵌套
- RecycleView滑动会感觉到卡顿,可以通过mRecyclerView.setNestedScrollingEnabled(false)解决这个问题
- 解决方案RecyclerView和NestedScrollView嵌套导致滑动卡顿
- 这个方法是如何解决滑动卡顿的,深入理解没????