- 一旦view滑出view,就会被会受到缓存中
- 一旦滑入屏幕,就会从缓存中拿
- 如果缓存中没有
- 如图
- ListView复用逻辑总结
- 先从mActiveViews中取
- 如果没有,从mScrapViews中取
- 如果还是没有,需要创建新的view返回使用
RecyclerView中的四级缓存
- mCachedViews
- 主要是优化滑动时的性能,默认情况下只能存放两个回收的viewHolder,可以通过setItemViewCacheSize自定义容积
- 向上滑动屏幕,当上面的item被移出屏幕时,如position0和position1会被存入mCachedViews
- 向下滑动屏幕,position1重新出现在屏幕范围内,会从mCachedViews中找有没有缓存position为1的view,存在就直接复用
- mCachedViews的缓存不会按照viewType进行分类,也就是说不同类型的viewHolder都可以存放在mCachedViews中,也就是说上面的滑入滑出操作不会执行onBindViewHolder
- 由于刚才的下拉操作,position6被移除屏幕,这时候它会被存在mCachedViews中
- 回收池mRecyclerPool
- 在上面的操作中,如果position2被移出屏幕,那么它会加入到mCachedViews中,而position0会被挤出去,加到mRecyclerPool回收池中
- ![rcy9.png](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2374c44de782476987d413e771b0059a~tplv-k3u1fbpfcp-watermark
《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享
.image)
private static final int DEFAULT_MAX_SCRAP = 5; static class ScrapData { ArrayList mScrapHeap = new ArrayList<>(); int mMaxScrap = DEFAULT_MAX_SCRAP; long mCreateRunningAverageNs = 0; long mBindRunningAverageNs = 0; } SparseArray mScrap = new SparseArray<>();
- 继续滑动,position1和position2重新回到屏幕,会从mCachedViews中去取,此时position6和position7滑出屏幕,进入mCachedViews,继续向下滑动,position0会从回收池中取出
- mRecyclerPool相对于ListView中mScrapViews的优化
- 支持多个RecyclerView共用同一个回收池
- 可以单独根据viewType设置缓存容量,针对性优化
- viewType的值由于不再是数组的索引,不需要连续,可以直接写R.layout.xxx作为viewType
- mAttachedScrap暂存区
- mAttachedScrap存放
- RecyclerView获取缓存的顺序,
- 先从mAttachedScrap暂存区中去取
- 然后是mCachedViews
- 然后是mRecyclerViewPool
- 与mCachedViews不同,作为一个暂时存放viewHodler的区域,只会在一次布局过程中临时保存viewholder,布局开始,RecyclerView把所有的布局都存到mAttachedScrap中,布局结束,即使暂存区中还有viewholder,也会被扔进回收池中
- mChangedScrap暂存区
- 数据发生改变的viewHolder会进入mChangedScrap暂存区
核心机制pre-layout/post-layout
当 RecyclerView 支持 pre/post-layout 机制,则可以明确数据发生改变前后所有 ItemView 的位置,这样就可以容易的作出预测性动画。
- RecyclerView在删除item、插入item、改变item的时候都为我们提供了动画,那么动画是如何实现的呢
- 预测性动画:notifyItemRemoved动画原理
- 如图
- 以notifyItemRemoved为例,B逐渐消失执行出场动画,C逐渐显示执行入场动画
- adapter通知B被移除,由此pre-layout就可以通过B被移除的通知判断C要被显示出来,就会在pre-layout时把C摆放起来,一旦被摆放起来,就可以确定动画的起始点
- 正因为这个机制,RecyclerView做预测性动画就变得容易
- 局部刷新:notifyItemSetChanged动画原理:
- notifyItemSetChanged实际上是两个item再做动画,老的item慢慢变得不透明,新的item逐渐变得透明,这似乎有违局部刷新的原理,但事实的确如此,这也是我们经常发现局部刷新图片闪烁的原因所在
- 之所以这样做,是因为存在这样的一种场景,执行变更的item所有数据都发生了改变,那么整个item都需要改变,而RecyclerView默认使用的就是完全替换的方式
- 高效的局部刷新:防止局部刷新图片闪烁的两种方式
- 方式一:可以使用setSupportChangeAnimations(false)来禁止预测性动画,不过这种方式也会使移除动画和插入动画失效
- 方式二:传入payload ->
notifyItemChanged(position,"payload");
RecyclerView 复用策略
- Scrap 中尝试获取
- Cache 中尝试获取
- 自定义缓存中尝试获取 (其实没有找到有意义的应用)
- Pool 中尝试获取
重新绑定数据,直接使用 3. 自定义缓存中尝试获取 (其实没有找到有意义的应用) 4. Pool 中尝试获取
|