一、背景
RecyclerView的优化有很多机制,一般来说主要分为:
(1)ViewHolder 缓存预加载
这类主要提前填充ViewHolder缓存或者共享ViewHolder来实现
(2)图片预加载
利用ScrollListener机制,预测滑动方向,但是存在明显的鸡肋就是ImageView或者ImageView所在的Item尽可能的相似,如果RecylerView的复用时算法复杂度越高,性能增益也会越低,主要取决于viewType数量和各种View的交替复杂度。
(3)局部更新
一般很难去使用单个的notifyItemXXX方法,但是Android提供了一个比较好的工具,DiffUtil来优化,但是缺点是大部分场景必须复写equals和hashcode,不过收益也不错。
(4)动画
动画在低配设备上差异很明显,特别是帧动画,alpha动画 (alpha动画是离屏渲染2次,且缓存会被回收),如果能避免动画尽可能避免,特别是低端机型。
(5) 对象、资源共享
不需要为每个ItemView去new 一个监听器
Drawable可以ConstantState.newDrawable或者mutate复用
(6)减少RequestLayout
这里特别说一下TextView,看似简单,实际上性能损耗不少
(9)不使用inflater
inflater确实又些性能损耗
(10)
不给ImageView设置图片或者背景
二、可是区域优化-预布局
getExtraLayoutSpace
返回 LayoutManager 应布置的额外空间量。
默认情况下,LinearLayoutManager 在平滑滚动时额外放置 1 页项目,否则为 0。您可以覆盖此方法以实现您的自定义布局预缓存逻辑。
注意:布置不可见元素通常会带来显着的性能成本。它通常只适用于平滑滚动到未知位置等地方,其中 1) 额外的内容有助于 LinearLayoutManager 提前知道其目标何时接近,因此它可以尽早平滑地减速,以及 2) 当运动是连续的。
如果在用户可能改变滚动方向的情况下扩展额外的布局空间,代价尤其昂贵。改变方向将导致额外的布局空间交换到视口的另一侧,导致许多重新绑定/回收,除非缓存足够大以处理它。
返回值:应布置的额外空间(以像素为单位)。
此方法是一把双刃剑,对于ViewType较少的情况,实际上增益并不大,反而有损内存空间,但是对于ViewType交错排列的情况,反而是一种改善方式,但是最好不要超过1屏的高度。另外也可以很好的结局TV上焦点移动时,新View未加载,focus Down 时焦点乱飞的问题。