You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无条件布局填充问题:如何使用ViewHolder模式优化滚动性能?

解决列表滚动卡顿:ViewHolder模式实战指南

嘿,作为刚入门的开发者,遇到列表滚动卡顿太正常啦!ViewHolder模式正是解决这个问题的核心方案,我来一步步给你拆解清楚怎么改~

为啥会卡顿?

每次列表滚动时,getView()方法会被频繁调用。如果每次都在方法里调用findViewById()去查找控件,这是个非常耗时的操作——系统得反复遍历布局树找控件,列表项越多、布局越复杂,卡顿就越明显。ViewHolder的本质就是把这些控件缓存起来,避免重复查找,从而提升滚动流畅度。

怎么用ViewHolder修复?

我直接给你对比新旧写法,一看就懂:

1. 先看你的原始(卡顿)写法

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    if (convertView == null) {
        convertView = LayoutInflater.from(context).inflate(R.layout.list_item, parent, false);
    }
    // 每次滚动都重新查找控件,耗时!
    TextView titleTv = convertView.findViewById(R.id.title_tv);
    ImageView iconIv = convertView.findViewById(R.id.icon_iv);
    
    // 设置数据
    titleTv.setText(dataList.get(position).getTitle());
    iconIv.setImageResource(dataList.get(position).getIconRes());
    return convertView;
}

2. 改成ViewHolder模式的写法

第一步:定义ViewHolder静态内部类

把列表项里所有需要操作的控件都放到这个类里,作为成员变量:

// 必须是静态内部类,避免内存泄漏
static class ViewHolder {
    TextView titleTv;
    ImageView iconIv;
    // 如果还有其他控件,比如Button、CheckBox,都加在这里
}

第二步:修改getView()方法,复用ViewHolder

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
    
    // 第一次加载布局时,初始化ViewHolder并绑定控件
    if (convertView == null) {
        convertView = LayoutInflater.from(context).inflate(R.layout.list_item, parent, false);
        holder = new ViewHolder();
        // 只在第一次查找控件,之后再也不用找了!
        holder.titleTv = convertView.findViewById(R.id.title_tv);
        holder.iconIv = convertView.findViewById(R.id.icon_iv);
        // 把ViewHolder存到convertView的Tag里,方便后续取出
        convertView.setTag(holder);
    } else {
        // 滚动复用布局时,直接从Tag里取出缓存的ViewHolder
        holder = (ViewHolder) convertView.getTag();
    }
    
    // 通过ViewHolder直接操作控件,设置数据
    holder.titleTv.setText(dataList.get(position).getTitle());
    holder.iconIv.setImageResource(dataList.get(position).getIconRes());
    
    return convertView;
}

额外优化小Tips

  • 图片加载别用同步加载:如果你的列表项里有网络图片,一定要用异步加载库,别在getView里直接加载,不然照样卡顿。
  • 避免在getView里做耗时操作:比如解析JSON、计算复杂数据,这些都要提前在子线程处理好,把结果存到数据源里,getView只负责显示数据。
  • 布局尽量扁平化:列表项的布局层级越少越好,减少系统绘制的压力,也能间接提升流畅度。

这样改完之后,你再试试滚动列表,应该就丝滑多啦!

内容的提问来源于stack exchange,提问作者niel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:44:23