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

RecyclerView动态移除随机项后位置异常及EditText内容丢失求助

问题解决方案

核心问题分析

你的代码存在几个关键问题:Model类错误持有View组件、添加逻辑重复复用同一实例、视图复用导致数据丢失、移除时位置处理不当,这些共同导致了移除位置错误和EditText内容清空的问题。以下是针对性修复:


1. 修正JournalEntryModel设计(核心)

Model类应存储数据而非View组件,确保数据独立保存:

public class JournalEntryModel {
    private String selectedAccount;
    private String debit;
    private String credit;

    public JournalEntryModel() {
        this.selectedAccount = "";
        this.debit = "";
        this.credit = "";
    }

    // Getter & Setter
    public String getSelectedAccount() { return selectedAccount; }
    public void setSelectedAccount(String selectedAccount) { this.selectedAccount = selectedAccount; }
    public String getDebit() { return debit; }
    public void setDebit(String debit) { this.debit = debit; }
    public String getCredit() { return credit; }
    public void setCredit(String credit) { this.credit = credit; }
}

2. 修复添加逻辑

每次点击添加按钮时创建新的Model实例,避免数据共享混乱:

ArrayList<JournalEntryModel> journalEntryModelsList = new ArrayList<>();
GeneralEntryAdapter adapter = new GeneralEntryAdapter(journalEntryModelsList,this,accountList);
binding.recyclerviewaddnewentry.setAdapter(adapter);

// 移除外部的Model初始化,改为点击时创建新实例
binding.btnAddLine.setOnClickListener(v -> {
    JournalEntryModel entryModel = new JournalEntryModel();
    journalEntryModelsList.add(entryModel);
    adapter.notifyItemInserted(journalEntryModelsList.size() - 1);
});

3. 重构Adapter代码

解决位置错误、数据丢失和性能问题:

public class GeneralEntryAdapter extends RecyclerView.Adapter<GeneralEntryAdapter.GeneralEntryViewHolder> {

    ArrayList<JournalEntryModel> journalEntryModelsList;
    Context context;
    ArrayAdapter<String> spinnerArrayAdapter; // 提前初始化Spinner适配器

    public GeneralEntryAdapter(ArrayList<JournalEntryModel> journalEntryModelsList, Context context, ArrayList<String> accountList) {
        this.journalEntryModelsList = journalEntryModelsList;
        this.context = context;
        // 仅初始化一次Spinner适配器
        spinnerArrayAdapter = new ArrayAdapter<>(context, android.R.layout.simple_spinner_item, accountList);
        spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    }

    @NonNull
    @Override
    public GeneralEntryViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.row_layaddnewentry, parent, false);
        return new GeneralEntryViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull GeneralEntryViewHolder holder, int position) {
        JournalEntryModel model = journalEntryModelsList.get(position);

        // 从Model加载Spinner选中状态
        holder.spinnerAccountType.setAdapter(spinnerArrayAdapter);
        int selectedIndex = spinnerArrayAdapter.getPosition(model.getSelectedAccount());
        if (selectedIndex != -1) {
            holder.spinnerAccountType.setSelection(selectedIndex);
        }

        // 从Model加载EditText内容
        holder.edtDebit.setText(model.getDebit());
        holder.edtCredit.setText(model.getCredit());

        // 监听Spinner选择,保存到Model
        holder.spinnerAccountType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
                model.setSelectedAccount(spinnerArrayAdapter.getItem(pos));
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
                model.setSelectedAccount("");
            }
        });

        // 监听EditText输入,保存到Model
        holder.edtDebit.addTextChangedListener(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) {
                model.setDebit(s.toString());
            }
            @Override
            public void afterTextChanged(Editable s) {}
        });

        holder.edtCredit.addTextChangedListener(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) {
                model.setCredit(s.toString());
            }
            @Override
            public void afterTextChanged(Editable s) {}
        });

        // 移除按钮:使用当前ViewHolder的有效位置
        holder.imgClose.setOnClickListener(view -> {
            int currentPosition = holder.getAdapterPosition();
            if (currentPosition != RecyclerView.NO_POSITION) {
                removeRow(currentPosition);
            }
        });
    }

    public void removeRow(int position){
        if (position >= 0 && position < journalEntryModelsList.size()){
            journalEntryModelsList.remove(position);
            notifyItemRemoved(position);
            // 更新后续项的位置,避免错乱
            notifyItemRangeChanged(position, journalEntryModelsList.size() - position);
        }
    }

    @Override
    public int getItemCount() {
        return journalEntryModelsList.size();
    }

    public class GeneralEntryViewHolder extends RecyclerView.ViewHolder {
        public EditText edtDebit, edtCredit;
        public Spinner spinnerAccountType;
        public ImageView imgClose;

        public GeneralEntryViewHolder(@NonNull View itemView) {
            super(itemView);
            edtDebit = itemView.findViewById(R.id.edtDebit);
            edtCredit = itemView.findViewById(R.id.edtCredit);
            spinnerAccountType = itemView.findViewById(R.id.spinnerAccountType);
            imgClose = itemView.findViewById(R.id.img_close);
        }
    }
}

修复说明

  1. 数据与视图分离:Model只存数据,不再持有View,确保数据持久化
  2. 独立实例添加:每次添加新行都创建新Model,避免数据共享
  3. 视图复用数据恢复:onBind时从Model读取数据填充,而非清空
  4. 正确位置处理:使用holder.getAdapterPosition()获取实时有效位置,移除后更新后续项位置
  5. 性能优化:Spinner适配器仅初始化一次,避免重复创建

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 20:00:09