RecyclerView的缓存机制是为了提高列表滚动时的性能。采用了多级缓存策略来存储和复用视图(View),减少视图的创建和销毁,进而减少内存分配和GC的频率。
缓存层级
负责回收和复用ViewHolder的类是Recycler,负责缓存的主要就是这个类的几个成员变量。
RecyclerView的缓存机制主要由四个部分组成,它们按照从高到低的优先级排列:
- 「Scrap缓存(Scrap Heap)」
包括mAttachedScrap和mChangedScrap,也称为屏内缓存,因为它们主要用于保存屏幕内当前可见或者即将可见的ViewHolder。
mAttachedScrap:存放的是已添加到RecyclerView但与RecyclerView临时分离(例如在滚动或布局调整过程中)的ViewHolder。
mChangedScrap:存放的是数据已改变但尚未重新绑定数据的ViewHolder,通常用于动画播放等场景。
- 「Cache缓存(mCachedViews)」
又称离屏缓存,用于保存最新被移除(remove)但尚未被回收的ViewHolder。
缓存的大小是有限制的,默认最大数量为2(由DEFAULT_CACHE_SIZE定义)。
当需要展示新视图时,会首先检查Cache缓存中是否有可用的ViewHolder。
「ViewCacheExtension」
为开发者预留的缓存池,允许开发者自定义缓存策略,存储更多的或特定类型的ViewHolder。
开发者可以通过实现ViewCacheExtension接口来扩展缓存功能。
「RecycledViewPool(mRecyclerPool)」
终极的回收缓存池,用于存放被标识为废弃(即其他缓存池不再需要的)的ViewHolder。
这些ViewHolder已经被抹除了数据,需要重新绑定数据才能使用。
RecycledViewPool会根据不同的item类型创建不同的List来存储ViewHolder。
缓存使用策略
- 「RecyclerView滚动时」:首先移除滑出屏幕的item,并将这些ViewHolder存入Cache缓存(mCachedViews)。如果Cache缓存已满,则将更旧的ViewHolder存入RecycledViewPool。
- 「数据更新时」:如果屏幕内的某个item数据发生变化,但ViewHolder仍然可见,那么这个ViewHolder会被放入mChangedScrap。当需要重新绑定数据时,会从这个缓存中取出ViewHolder。
- 「删除item时」:被删除的item对应的ViewHolder首先会进入Scrap缓存,然后可能会被移入Cache缓存或RecycledViewPool。
「注意」:当RecyclerView不再需要某个ViewHolder时(例如,当列表项被完全移出屏幕并且缓存已满时),ViewHolder会被放入RecycledViewPool并最终可能被系统回收。
缓存机制的好处
- 「减少视图创建和销毁」:通过复用已有的ViewHolder,大大减少视图的创建和销毁次数,从而节省内存和提高性能。
- 「优化滚动性能」:当滚动列表时,由于大部分视图都可以从缓存中快速获取,可以保持流畅的滚动体验。
- 「降低GC频率」:由于减少了视图的创建和销毁,也降低了GC的频率,进一步提高了应用的性能。