android recyclerview缓存2_四级缓存机制
RecyclerView 的缓存机制设计得非常精妙,主要分为 四级缓存机制,用来实现「滑动流畅」与「避免重复创建 ViewHolder」。
🧩 一、RecyclerView 的四级缓存机制
RecyclerView 内部的缓存体系主要存在于 Recycler 对象中,它有 4 级缓存层次:
| 缓存级别 | 缓存位置 | 缓存内容 | 命中条件 | 是否需要重新绑定数据 |
|---|---|---|---|---|
| 1️⃣ Scrap 缓存 | mAttachedScrap / mChangedScrap | 当前屏幕中暂时被移除但仍附着的 ViewHolder | position 相同 | 不需要 |
| 2️⃣ Recycler 缓存池 | mCachedViews | 刚刚离开屏幕的 ViewHolder(仍与 Adapter 数据对应) | position 相同 | 可能需要绑定(如果数据变化) |
| 3️⃣ ViewCacheExtension(可选) | 自定义缓存逻辑 | 自定义 ViewHolder 缓存策略 | 自定义 | 可自定义是否重新绑定 |
| 4️⃣ RecycledViewPool(共享池) | RecycledViewPool | 可复用的 ViewHolder(按 viewType 分类) | viewType 相同 | 需要重新绑定 |
🧠 二、缓存机制的工作流程
假设 RecyclerView 滑动时有一个 item 被移出屏幕,那么流程如下:
🔹 1. 从屏幕上移除
当一个 Item 滑出屏幕:
- RecyclerView 会先尝试把对应的 ViewHolder 放入
mCachedViews。 - 如果
mCachedViews已经满(默认容量是 2),则最旧的 ViewHolder 会被移入RecycledViewPool。
🔹 2. 获取可复用的 ViewHolder
当 RecyclerView 需要显示一个新的 item 时,会按以下顺序查找缓存:
1️⃣ mAttachedScrap / mChangedScrap
- 如果 item 仍在屏幕中(比如执行动画时),会从这里直接取出。
2️⃣ mCachedViews
- 如果滑动回到刚刚移出屏幕的 item,通常能直接命中,极快。
3️⃣ ViewCacheExtension(如果开发者自定义了)
- 提供更灵活的缓存机制。
4️⃣ RecycledViewPool
- 如果前几级都找不到,会从全局池中根据
viewType获取可复用的 ViewHolder。
5️⃣ 最终创建新 ViewHolder
- 如果四级缓存都 miss,则调用 Adapter 的
onCreateViewHolder()重新创建。
🪣 三、各缓存的关系图
Recycler├── mAttachedScrap // 屏幕中可见或刚移除的ViewHolder├── mCachedViews (size=2) // 最近离开的item缓存├── ViewCacheExtension // 开发者自定义缓存扩展└── RecycledViewPool // 全局池(按viewType存放)
⚙️ 四、RecycledViewPool 的意义
RecycledViewPool 是可 在多个 RecyclerView 之间共享的缓存池。
例如 ViewPager+RecyclerView 或多 Tab 列表场景,可以让不同 RecyclerView 共享 ViewHolder,减少重复创建的开销:
val pool = RecycledViewPool()
recyclerView1.setRecycledViewPool(pool)
recyclerView2.setRecycledViewPool(pool)
可以通过以下方法设置每种类型的最大缓存数:
pool.setMaxRecycledViews(VIEW_TYPE_ITEM, 10)
🧮 五、关键源码位置(理解加分)
主要类:
RecyclerView.Recycler(负责回收与复用逻辑)RecyclerView.RecycledViewPool(全局缓存池)Adapter.createViewHolder()/bindViewHolder()
核心方法:
Recycler.getViewForPosition()Recycler.tryGetViewHolderForPositionByDeadline()
✅ 六、总结对比表
| 缓存层级 | 存放位置 | 特点 | 命中率 | 是否重新bind |
|---|---|---|---|---|
| mAttachedScrap | 当前屏幕内 | 临时存放 | 高 | 否 |
| mCachedViews | 最近离屏 | 数量有限(2) | 高 | 有时 |
| ViewCacheExtension | 可选自定义 | 灵活 | 不定 | 自定义 |
| RecycledViewPool | 全局共享 | 按类型分池 | 中 | 是 |
💡 面试高分总结回答模板:
RecyclerView 采用四级缓存机制来提高复用率与滑动性能,分别是:
- Scrap 缓存:缓存当前屏幕中临时移除的 ViewHolder。
- Cached 缓存:缓存刚离开屏幕的少量 ViewHolder。
- ViewCacheExtension:开发者可自定义缓存逻辑。
- RecycledViewPool:按 viewType 分类的全局复用池,可多个 RecyclerView 共享。
当 RecyclerView 需要新的 View 时,会依次从这些缓存中查找可复用的 ViewHolder,若找不到才创建新的。
这套机制极大地提升了性能,避免了频繁创建 View 和调用onCreateViewHolder()的开销。
