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 | mRecyclerView.setItemViewCacheSize(20); |
避免创建过多对象
onCreateViewHolder 和 onBindViewHolder 对时间都比较敏感,尽量避免繁琐的操作和循环创建对象。例如创建 OnClickListener,可以全局创建一个,然后数据通过 itemView.setTag 携带。
局部刷新
可以用一下一些方法,替代notifyDataSetChanged,已达到局部刷新的目的。
1 | notifyItemChanged(int position) |
如果必须用 notifyDataSetChanged(),那么最好设置 mAdapter.setHasStableIds(true)