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

ListView的getView()获取位置异常,滚动时显示错误位置的解决方法

解决ListView滚动时Item位置偏移的问题

嘿,看了你的代码,问题根源就在ViewHolder的复用逻辑上——你漏了最关键的一步:把初始化好的ViewHolder绑定到View的Tag上,导致复用的时候拿不到正确的ViewHolder对象,进而出现滚动时数据绑定混乱、位置偏移的问题。

直接修复代码

修改ListAdapter里的getView方法,重点补全view.setTag(holder)这一步:

public View getView(int position , View view, ViewGroup parent ){
    Log.d(TAG, "position=" + position);
    ViewHolder holder; // 先声明,不要每次都直接new
    if(view == null){
        LayoutInflater inflater = context.getLayoutInflater();
        view = inflater.inflate(R.layout.listview_chat_room_me,parent,false);
        holder = new ViewHolder(); // 只有当View是新创建时,才初始化ViewHolder
        holder.name_text = view.findViewById(R.id.txtName);
        holder.time_text = view.findViewById(R.id.txtTime);
        holder.message_text = view.findViewById(R.id.txtMessage);
        holder.image = view.findViewById(R.id.imgPersonalPhoto);
        view.setTag(holder); // 核心!把ViewHolder绑定到View的Tag上,方便后续复用
    } else{
        holder = (ViewHolder) view.getTag(); // 复用View时,直接从Tag取出对应的ViewHolder
    }
    try {
        holder.name_text.setText(list_name.get(position));
        holder.time_text.setText(list_time.get(position));
        holder.message_text.setText(list_message.get(position));
        Glide.with(context).load(list_image.get(position)).into(holder.image);
    } catch (Exception e){
        e.printStackTrace(); // 建议打印异常,别直接吞掉,方便排查问题
    }
    return view;
}

错误原因拆解

你原来的代码有两个明显问题:

  1. 每次调用getView都先new一个ViewHolder,当View复用的时候,从Tag取的holder和你新new的holder冲突,而且第一次创建View时根本没把holder绑定到Tag上,view.getTag()拿到的是null,强制转换会抛出异常(你用try-catch掩盖了这个错误,导致数据没绑定成功)
  2. 异常触发后数据绑定失效,再加上ListView的View复用机制,就会出现滚动时Item位置偏移、数据乱跳的情况

额外优化建议

你现在用四个ArrayList来存数据,维护起来很麻烦,建议自定义一个数据类封装所有字段:

public class ChatItem {
    private String name;
    private String time;
    private String message;
    private String imageUrl;

    public ChatItem(String name, String time, String message, String imageUrl) {
        this.name = name;
        this.time = time;
        this.message = message;
        this.imageUrl = imageUrl;
    }

    // 生成getter方法
    public String getName() { return name; }
    public String getTime() { return time; }
    public String getMessage() { return message; }
    public String getImageUrl() { return imageUrl; }
}

然后把Adapter改成继承ArrayAdapter<ChatItem>,这样只需要维护一个ArrayList<ChatItem>,在getView里直接通过ChatItem item = getItem(position)获取数据,代码更整洁,也不容易出错。

内容的提问来源于stack exchange,提问作者曾奕堯

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:53:59