RecycleView优化
1、Recycle缓存
1.1三级缓存
a)Attached scrap & Changed scrap
ArrayList mAttachedScrap可见ViewHolder;
ArrayList mChangedScrap主要用到刷新屏幕上的itemView数据;
b)cache Views
ArrayList mCachedViews :保存最近移出屏幕的ViewHolder,包含数据和position信息,复用时必须是相同位置的ViewHolder才能复用,应用场景在那些需要来回滑动的列表中,当往回滑动时,能直接复用ViewHolder数据,不需要重新bindView。用一个数组保存ViewHolder;
c)RecyclerViewPool
SparseArray<ArrayList> mScrap:缓存池,当cacheView满了后,将cacheView中移出的ViewHolder放到Pool中,放之前会把ViewHolder数据清除掉,所以复用时需要重新bindView。按viewType来保存ViewHolder,每种类型最大缓存个数默认为5
1.2调用notifyDataSetChanged过程
如果没有设置Stable Ids,RecyclerView不知道哪些改变,它假设所有都改变了,会将每一个ViewHolder设置成无效并且放到缓存池Pool中。如果我们仅是把屏幕上的第四条itemView移到第六条的位置,屏幕上所有itemView都会重新layout一遍,这样只能从缓存池RecycledViewPool池中取缓存的ViewHolder,如果不够时,需要重新create ViewHolder.
如果设置了Satable Ids,即每一个itemView都有一个唯一的id来标识,通过getItemId()来获取这个唯一标识id,当然我们不能用position来标识,因为itemView会复用,位置会乱序。当调用notifyDataSetChanged()方法时,ViewHolder会进入上面的一级缓存mAttachedScrap中,而不是进入缓存池pool中,这样的好处:1)不会存在缓存池pool满的问题,不需要重新createViewHolder; 2) 不需要重新bindView了
2、Recycle优化:
Recycle优化这一块有两个角度的优化,一个UI级别的,还有一个就是数据级别的,下面分开介绍:
UI优化
2.1 View优化
纯UI布局的优化,这里不讲太多,删除无用层级,减少过度绘制,ViewStub的使用等等。这里额外讲一个优化点:AsyncLayoutInflater。我们打开一个list界面,显示刷新数据,然后在交给RecycleView渲染数据,我们观察页面的GPU Rending的渲染时间柱状图,发现RecycleView第一次加载展示数据会比较耗时,主要是这个有onCreateViewHolder进行View的初始化创建。如果item的view比较复杂,没有优化空间导致了卡顿,我们可以利用AsyncLayoutInflater预加载UI,具体的实现可以参考之前的App启动时间优化中的View提前加载,这里不多提。