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); } } }
修复说明
- 数据与视图分离:Model只存数据,不再持有View,确保数据持久化
- 独立实例添加:每次添加新行都创建新Model,避免数据共享
- 视图复用数据恢复:onBind时从Model读取数据填充,而非清空
- 正确位置处理:使用
holder.getAdapterPosition()获取实时有效位置,移除后更新后续项位置 - 性能优化:Spinner适配器仅初始化一次,避免重复创建
内容的提问来源于stack exchange,提问作者Pratiksha Shaha
相关产品推荐
相关产品推荐

