RecyclerView 性能优化

RecyclerView 几乎已经取代了 ListView & GridView,但为了达到更好的性能体验,还是需要做一些适当的优化的。

  • 布局优化
  • 取消默认动画
  • Item 等高
  • RecycledViewPool
  • 避免创建过多对象
  • 局部刷新

布局优化

首当其冲,减少层次结构、减少过渡绘制,可以提高item的解析测量与绘制的效率。另外,应该尽量避免多次measure & layout 次数。

1、 View 的三大过程
从ViewRoot的 performTraversals() 方法开始,依次经过 measure()layout()draw() 三个过程才最终将一个View绘制出来。

2、ViewGroup 性能
相比之下,FrameLayout & LinearLayout 的 measure 要远优于 RelativeLayout,因为 RelativeLayout 对子View做了两次measure,才能确定宽高,因为子View之间有彼此依赖的关系。但是LinearLayout 的子View如果加上了 layout_weight 的属性,也需要进行两次测量。

取消默认动画

取消RecyclerView的默认动画,也可改善一些。

1
mRecyclerView.setItemAnimator(null);

Item 等高

如果可以的话,把所有的 Item 的高度固定大小,这样可以减少测量次数,尤其是对于 GridLayoutManager。

1
mRecyclerView.setHasFixedSize(true);

RecycledViewPool

可以给RecyclerView设置一个ViewHolder的对象池,这个池称为RecycledViewPool,这个对象池可以节省你创建ViewHolder的开销,更能避免GC。默认会自动创建一个。

1
RecycledViewPool mPool = mRecyclerView.getRecycledViewPool();

RecycledViewPool可以自主控制需要缓存的ViewHolder数量:

1
mPool.setMaxRecycledViews(itemViewType, number);

RecyclerView可以设置自己所需要的ViewHolder数量:

1
mRecyclerView.setItemViewCacheSize(10);

那么,可以按需调整draw缓存

1
2
3
mRecyclerView.setItemViewCacheSize(20);
mRecyclerView.setDrawingCacheEnabled(true);
mRecyclerView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);

避免创建过多对象

onCreateViewHolder 和 onBindViewHolder 对时间都比较敏感,尽量避免繁琐的操作和循环创建对象。例如创建 OnClickListener,可以全局创建一个,然后数据通过 itemView.setTag 携带。

局部刷新

可以用一下一些方法,替代notifyDataSetChanged,已达到局部刷新的目的。

1
2
3
4
5
6
7
notifyItemChanged(int position)
notifyItemInserted(int position)
notifyItemRemoved(int position)
notifyItemMoved(int fromPosition, int toPosition)
notifyItemRangeChanged(int positionStart, int itemCount)
notifyItemRangeInserted(int positionStart, int itemCount)
notifyItemRangeRemoved(int positionStart, int itemCount)

如果必须用 notifyDataSetChanged(),那么最好设置 mAdapter.setHasStableIds(true)

~沙漠尽头必是绿洲~