安卓白话文面试(9) —— ListView/RecyclerView缓存?餐厅的“餐具回收”机制

7 阅读4分钟

你有没有在自助餐厅里遇到过这种事:高峰期盘子不够用,服务员一边收脏盘子一边给新来的客人用,你端着食物干等着。这时候要是有一套高效的餐具回收流程,客人吃完一拨,盘子马上洗干净摆回来,大家都不用等。

安卓里的ListViewRecyclerView就是干这个活的——滑动列表时,不停创建新的Item视图太耗内存,必须把滑出屏幕的“旧盘子”回收再利用。说白了,就是视图复用

一、ListView的“餐具回收”——RecycleBin

早期的ListView内部有个叫RecycleBin的管家。你可以想象:餐厅里每个餐桌(屏幕上的每个item)撤下来后,服务员不会直接扔进洗碗机,而是先放在手边的小推车上。

ListView的回收分两块:

  • Active Views:屏幕边缘即将进场或刚刚退场的item,处于“待命区”,还不是正在用餐的盘子。
  • Scrap Views:已经滑出屏幕的item,被放进一个“临时缓存区”。下次需要新item时,优先从这里面拿,拿到后调用getView()重新绑定数据。

但有个痛点:ListView不区分item的类型(比如你的列表里有头部、正文、广告三种样式),所有盘子混在一起。服务员从混在一起的推车里拿出来的盘子可能是广告用的金盘子,但你只想装米饭——这就是getView()里那个convertView参数为null的原因,只能重新造一个。

二、RecyclerView的“智能回收”——多级缓存

RecyclerView像是一家更精细的现代化餐厅。它把回收流程分成四层,每一层对应不同的“盘子状态”:

  1. 一级缓存(mAttachedScrap):刚撤下来的热乎盘子,布局重新计算时直接用,不需要重新走onCreateViewHolder()。通常用于屏幕内Item的位置微调或notifyDataSetChanged()后的重新布局。至于要不要重新摆盘(绑定数据),看具体情况——如果数据没变,就不用动。

  2. 二级缓存(mCachedViews):撤下来的盘子简单冲一下,放在手边。默认大小2,虽然不需要重新创建(不走onCreateViewHolder()),但取出时还是要重新摆盘(走onBindViewHolder()。适合快速来回滑动时快速复用。

  3. 三级缓存(ViewCacheExtension):留给开发者自己定制的“特殊餐具柜”,比如你非要给VIP客人用金盘子,自己控制怎么取放。

  4. 四级缓存(RecycledViewPool):真正的洗碗机+消毒柜。不同ViewType(不同样式的item)有各自的池子,并且可以跨多个RecyclerView共享(比如ViewPager里两个列表共用缓存)。池子里的盘子必须重新摆盘绑定数据)才能用。ListView缺的就是这个——按类型分离,不会拿广告样式去当正文用。

整个过程像流水线:服务员先看手边有没有干净的(一级),没有就去小推车看看(二级),再没有就去洗碗机拿(四级),最后才现造一个盘子。

三、面试官爱怎么问?

问:RecyclerView比ListView好在哪?

答:就好比手工作坊 vs 自动化流水线ListView缓存级别少、不区分ViewType,容易“拿错盘子”。RecyclerView强制使用ViewHolder,设计了四级缓存 + 按类型分池,还支持跨列表共享缓存、动画、局部刷新,滑动更顺滑。

问:如果RecyclerView出现图片错位或内容闪烁,怎么排查?

答:通常是缓存复用导致的。检查onBindViewHolder()里是否重置了所有可见状态。因为四级缓存池里的“盘子”是洗过但可能还有之前客人的“水渍”(旧数据残留),比如之前加载的图片没清空,新位置又异步加载了旧图。解决办法就是每次绑定都把图片先清掉,再加载新的。

四、总结表格

对比点ListView(老式餐厅)RecyclerView(智能餐厅)
缓存级别2级(Active + Scrap)4级(AttachedScrap / CachedViews / 开发者定制 / ViewPool)
是否按ViewType区分❌ 所有盘子混在一起✅ 每种样式独立池子,可跨列表共享
是否强制ViewHolder❌ 可选✅ 强制,架构基础
取出时是否重新绑定Scrap取出必调getView()CachedViews需重新绑定;AttachedScrap视情况
扩展性强(可自定义缓存策略、布局管理器、动画)

五、人话总结

ListView就是服务员手忙脚乱地传盘子,RecyclerView则是给盘子贴了分类标签、还分了手边和洗碗池的智能回收流水线,连盘子样式都强制统一了。


汇总导航

安卓白话文面试导航