RecyclerView筛选后Item选中对应原始列表错误问题求助
RecyclerView筛选后Item选中异常问题修复
问题现象
使用自定义PayloadAdapter实现按服务器名称筛选功能后,选中筛选列表中的项时,实际选中的是原始未筛选列表对应位置的条目,而非当前筛选列表的项。例如点击筛选后的第一项,实际选中的是原始列表的第一项。
问题根源
你的Adapter存在两个核心错误:
- 初始化时
payloadListFiltered直接引用原始payloadList,导致两个列表指向同一内存地址,筛选逻辑完全失效 onBindViewHolder和getItemCount始终使用原始payloadList,而非筛选后的payloadListFiltered,导致筛选后UI展示的是筛选数据,但点击位置对应的还是原始列表的索引
修复方案
步骤1:分离列表引用
将筛选列表初始化为新的ArrayList,避免与原始列表共享内存空间
步骤2:统一数据源
在onBindViewHolder、getItemCount中使用payloadListFiltered作为数据源
步骤3:优化点击事件(可选)
直接传递选中的PayloadModel对象,而非位置索引,从根源避免位置匹配错误
修改后的PayloadAdapter代码
public class PayloadAdapter extends RecyclerView.Adapter<PayloadAdapter.ViewHolder> implements Filterable { private final List<PayloadModel> payloadList; // 原始全量数据 public SimpleDraweeView selectedSImage; private OnItemClickListener listener; private final List<PayloadModel> payloadListFiltered; // 筛选后的数据 public PayloadAdapter(List<PayloadModel> payloadList) { this.payloadList = payloadList; this.payloadListFiltered = new ArrayList<>(payloadList); // 初始化新列表,避免引用同一对象 } @NonNull @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.spinner_item, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { // 改用筛选后的列表获取数据 PayloadModel payload = payloadListFiltered.get(position); holder.bind(payload); } @Override public int getItemCount() { // 返回筛选列表的长度 return payloadListFiltered.size(); } @Override public Filter getFilter() { return new Filter() { @Override protected FilterResults performFiltering(CharSequence charSequence) { String query = charSequence.toString().toLowerCase().trim(); List<PayloadModel> filteredList = new ArrayList<>(); if (query.isEmpty()) { filteredList.addAll(payloadList); } else { for (PayloadModel payload : payloadList) { if (payload.getServerName().toLowerCase().contains(query)) { filteredList.add(payload); } } } FilterResults results = new FilterResults(); results.values = filteredList; return results; } @Override protected void publishResults(CharSequence charSequence, FilterResults filterResults) { payloadListFiltered.clear(); payloadListFiltered.addAll((List<PayloadModel>) filterResults.values); notifyDataSetChanged(); } }; } private void loadPayloadIcon() { neth("ze"); } public void neth(String pogiko) { String flagUrl = "" + pogiko + ".webp"; selectedSImage.setImageURI(flagUrl); } // 优化接口:直接传递选中的对象,而非位置 public void setOnItemClickListener(OnItemClickListener listener) { this.listener = listener; } public interface OnItemClickListener { void onItemClick(PayloadModel payload); } public class ViewHolder extends RecyclerView.ViewHolder { TextView nameTextView, infoTextView; public ViewHolder(@NonNull View itemView) { super(itemView); nameTextView = itemView.findViewById(R.id.itemNamea); infoTextView = itemView.findViewById(R.id.sinf); selectedSImage = itemView.findViewById(R.id.itemImagea); } public void bind(PayloadModel payload) { nameTextView.setText(payload.getServerName()); infoTextView.setText(payload.getPayloadInfo()); loadPayloadIcon(); itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (listener != null) { int position = getAdapterPosition(); if (position != RecyclerView.NO_POSITION) { // 传递筛选列表中的对应对象 listener.onItemClick(payloadListFiltered.get(position)); } } } }); } } }
修改后的PayloadActivity代码(对应接口调整)
public class PayloadActivity extends BaseActivity implements PayloadAdapter.OnItemClickListener { EditText editTextSearch; private wamp config; private Settings mConfig; private List<PayloadModel> payloadList; private PayloadAdapter adapter; private RecyclerView recyclerView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.server); final EditText editTextSearch = findViewById(R.id.editTextSearch); payloadList = new ArrayList<>(); recyclerView = findViewById(R.id.recyclerView); recyclerView.setLayoutManager(new LinearLayoutManager(this)); adapter = new PayloadAdapter(payloadList); recyclerView.setAdapter(adapter); adapter.setOnItemClickListener(this); loadPayloadData(); editTextSearch.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {} @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { adapter.getFilter().filter(charSequence); } @Override public void afterTextChanged(Editable editable) {} }); } // 实现修改后的接口,直接获取选中的对象 @Override public void onItemClick(PayloadModel payload) { // 直接使用选中的payload对象处理业务逻辑,无需通过位置查找 } }
关键修复点说明
- 列表引用分离:初始化
payloadListFiltered时创建新的ArrayList,避免和原始列表共享内存空间,确保筛选操作不会修改原始数据 - 数据源统一:Adapter的所有数据操作(绑定、计数)都使用筛选后的列表,保证UI展示和数据索引一致
- 点击事件优化:直接传递选中的对象,彻底避免位置索引匹配错误的问题,代码逻辑更直观可靠
内容的提问来源于stack exchange,提问作者krypt central
相关产品推荐
相关产品推荐

