0赞
赏
赞赏
更多好文
写过Android列表的,谁没被ListView的“视图错乱”坑过?我去年调了一个月的列表,最后发现根本不是数据问题——是缓存机制在作妖。今天不扯理论,就聊聊这两个控件的缓存到底咋回事,顺便说说为啥现在没人敢碰ListView了。
ListView:简单粗暴的“老黄牛”缓存
ListView的缓存机制就一句话:滑出屏幕的View,塞进一个叫RecycleBin的筐里,滑进来直接拿出来用。
getView()里,你得自己写:
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.item, null);
} else {
// 直接复用!
}
问题在哪?
- 筐太小:只缓存最近滑出的几个View,一滚快了,筐里没货,直接
null重建,卡顿直接拉满。 - 数据污染:比如你给Item设了
TextView.setText("加载中"),滑出后没清空,复用时突然显示“加载中”——这坑我踩过三次,每次都要骂一句“这破ListView”。
RecyclerView:懒人福音的“智能缓存池”
RecyclerView不是升级版,是彻底重构。它把缓存玩成了“智能快递站”:
- 全局缓存池(
RecycledViewPool)
你建了5个RecyclerView?缓存池自动共享,不用每个列表自己造筐。
(比如APP首页列表和详情页列表,能复用同一个图片加载的ViewHolder) - 按需缓存(
ViewHolder绑定)
onBindViewHolder()里直接绑定数据,不关心View怎么来的。
(再也不用在getView里写if (convertView == null)这种冗余代码了) - 回收策略更狠
滑出屏幕的View,先放“临时仓库”(ViewCacheExtension),不用立刻回收。
(比如快速滑动时,仓库里的View能立刻顶上,不用等重建)
为什么RecyclerView能吊打ListView?
我拿真实项目对比过:
- ListView:1000条数据,滚动时CPU飙到90%,偶尔闪屏。
- RecyclerView:同样数据,滚动丝滑,CPU 30%左右,没见错乱过。
关键区别:
| 机制 | ListView | RecyclerView |
|---|---|---|
| 缓存范围 | 单列表独立缓存 | 全局缓存池+自定义扩展 |
| 视图复用逻辑 | 你手动判断convertView | 系统自动复用ViewHolder |
| 数据污染风险 | 高(需手动清空) | 低(绑定时重置数据) |
| 复杂场景支持 | 网格/瀑布流要自己写 | LayoutManager直接支持 |
给新人的血泪建议
- 别碰ListView了,除非是Android 4.0以下的老项目。
- RecyclerView的缓存别乱调:
- 如果列表里有图片,
RecyclerView默认会缓存图片,但别开setHasFixedSize(true)(会卡住) - 用
setItemViewCacheSize(20)手动调缓存池大小,20够用,别塞太多(内存泄漏警告!)
- 如果列表里有图片,
- 重点:
onBindViewHolder里必须重置View状态!@Override public void onBindViewHolder(MyViewHolder holder, int position) { holder.text.setText(data.get(position)); // 别忘了!如果Item有图片,这里清空占位图 holder.imageView.setImageResource(R.drawable.placeholder); }
最后一句大实话
ListView的缓存像老式缝纫机——能用,但卡顿得让你想砸屏幕。RecyclerView的缓存是智能洗衣机,甩干甩得飞起,还自带烘干。
别再为ListView的缓存问题熬夜了,升级RecyclerView,你的时间比代码值钱。
(写完这篇,我删了项目里最后1个ListView——真香。)
