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

RecyclerView滚动时项值异常:滚动后项内容替换、EditText值消失、Spinner自动变更

嘿,这个问题我太熟了!你遇到的其实是RecyclerView ViewHolder复用机制挖的经典坑——滚动时系统会把离屏的ViewHolder回收再重新绑定给新条目,要是没给每个条目单独存好状态,就会出现内容串位、输入值消失、Spinner自动变选中项的情况。我给你一步步拆解解决办法:

一、先搞懂问题根源

RecyclerView为了提升性能,不会每次滚动都新建ViewHolder,而是重复利用已经创建过的。如果你的Adapter没给每个列表条目独立保存状态,当ViewHolder被复用给另一个条目时,就会把之前条目的内容“带过去”,比如EditText的旧输入值、Spinner的旧选中项,自然就出现了你看到的混乱情况。

二、一步步解决问题

1. 先给数据模型加状态存储

首先,你的数据类(比如假设叫ItemModel)必须包含每个条目对应的EditText输入值、Spinner选中位置的字段,让每个条目都有自己的状态容器:

public class ItemModel {
    // 保留你原来的其他字段
    private String editTextContent; // 存EditText的输入内容
    private int spinnerSelectedPos; // 存Spinner选中的位置

    // 别忘了加对应的getter和setter
    public String getEditTextContent() {
        return editTextContent;
    }

    public void setEditTextContent(String editTextContent) {
        this.editTextContent = editTextContent;
    }

    public int getSpinnerSelectedPos() {
        return spinnerSelectedPos;
    }

    public void setSpinnerSelectedPos(int spinnerSelectedPos) {
        this.spinnerSelectedPos = spinnerSelectedPos;
    }
}

2. 在Adapter里正确绑定+恢复状态

在onBindViewHolder方法里,要把数据模型里存的状态赋值给对应View,同时给EditText和Spinner设置带位置标记的监听器,避免复用导致的监听混乱:

处理EditText的核心代码

@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
    ItemModel currentItem = mDataList.get(position);
    
    // 先恢复之前保存的EditText内容
    holder.itemEditText.setText(currentItem.getEditTextContent());
    
    // 关键!先移除旧的监听,不然复用会触发多个监听
    holder.itemEditText.removeTextChangedListener(holder.textWatcher);
    
    // 创建新的TextWatcher,实时把输入内容存回数据模型
    holder.textWatcher = new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {}

        @Override
        public void afterTextChanged(Editable s) {
            // 用holder.getAdapterPosition()拿当前真实位置,别直接用方法里的position(复用会失效)
            int realPos = holder.getAdapterPosition();
            if (realPos != RecyclerView.NO_POSITION) {
                mDataList.get(realPos).setEditTextContent(s.toString());
            }
        }
    };
    holder.itemEditText.addTextChangedListener(holder.textWatcher);
}

处理Spinner的核心代码

@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
    ItemModel currentItem = mDataList.get(position);
    
    // 恢复之前保存的Spinner选中位置
    holder.itemSpinner.setSelection(currentItem.getSpinnerSelectedPos());
    
    // 同样先清空旧的监听
    holder.itemSpinner.setOnItemSelectedListener(null);
    
    // 设置新的选中监听,把选中位置存回数据模型
    holder.itemSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
            int realPos = holder.getAdapterPosition();
            if (realPos != RecyclerView.NO_POSITION) {
                mDataList.get(realPos).setSpinnerSelectedPos(pos);
            }
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {}
    });
}

3. 优化ViewHolder:保存监听器引用

为了方便移除旧监听器,建议在ViewHolder里保存TextWatcher的引用:

public class MyViewHolder extends RecyclerView.ViewHolder {
    EditText itemEditText;
    Spinner itemSpinner;
    TextWatcher textWatcher; // 存TextWatcher引用,方便后续移除

    public MyViewHolder(@NonNull View itemView) {
        super(itemView);
        itemEditText = itemView.findViewById(R.id.et_item);
        itemSpinner = itemView.findViewById(R.id.spinner_item);
    }
}
三、额外避坑提醒
  • 如果列表有增删操作,一定要调用notifyDataSetChanged()或者更精细的更新方法(比如notifyItemInserted()),前提是数据模型里的状态已经正确保存。
  • 别在onCreateViewHolder里设置和位置相关的监听器,因为ViewHolder是复用的,那里设置的监听器会绑定到所有复用的条目上,只会越搞越乱。
  • 如果EditText有焦点乱跑的问题,可以在onBindViewHolder里加一句holder.itemEditText.clearFocus();,避免滚动时焦点自动跳转到其他条目。

按照这些步骤修改你的Adapter,应该就能彻底解决滚动后内容错乱、值丢失的问题啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 08:28:35