RecyclerView搜索过滤后点击Item传递错误数据问题求助
问题根源与解决方案
这个坑我太熟了!刚做RecyclerView搜索过滤的开发者十有八九会踩这个雷,咱们先把问题掰明白:
你在点击回调onNoteClick里用FoodList.get(position)获取数据,但这里的position是过滤后列表的索引,而FoodList是原始的完整列表——两者的索引对应的数据完全不匹配!比如过滤后列表的第一个元素可能是原始列表的第三个,你用position=0去原始列表取,拿到的自然是错误数据。
下面给你两种解决方案,推荐第一种,从根源上避免索引混乱:
方案一:直接传递点击的Item对象(推荐)
让Adapter在点击时直接把当前Item的FoodModel对象传出来,而不是传索引,彻底绕开索引不匹配的问题。
修改步骤:
- 更新Adapter的回调接口:
把OnNoteListener的参数从int position改成FoodModel food:
public interface OnNoteListener{ void onNoteClick(FoodModel food); }
- 修改ViewHolder的点击逻辑:
在onClick方法里直接获取当前Adapter列表中对应位置的对象并传递:
@Override public void onClick(View view) { // 从Adapter当前持有的列表中获取点击的Item数据 FoodModel clickedFood = productList.get(getAdapterPosition()); onNoteListener.onNoteClick(clickedFood); }
- 更新Activity的回调实现:
直接使用传递过来的对象,不用再通过索引取数据:
@Override public void onNoteClick(FoodModel food) { Intent intent = new Intent(this, sample_layout.class); intent.putExtra("foods", food); startActivity(intent); }
方案二:确保用Adapter当前的列表取数据(兼容原有接口)
如果不想修改接口,就必须保证点击时从Adapter当前显示的列表中取数据,同时要先修复一个潜在问题:你的Adapter里productList是static的,这会导致多个Adapter实例共享数据,非常容易出bug,先去掉static!
修改步骤:
- 去掉Adapter中列表的static修饰符:
把private static List<FoodModel> productList;改成:
private List<FoodModel> productList;
- 给Adapter加一个获取当前列表的方法:
在FoodAdapter中添加:
public List<FoodModel> getCurrentList() { return productList; }
- 更新Activity的点击回调:
从Adapter当前的列表中取数据,而不是原始的FoodList:
@Override public void onNoteClick(int position) { FoodModel food = foodAdapter.getCurrentList().get(position); Intent intent = new Intent(this, sample_layout.class); intent.putExtra("foods", food); startActivity(intent); }
额外优化:避免重复创建Adapter
你的SearchFilter方法每次搜索都new一个新的Adapter,完全没必要,直接调用Adapter已有的filteredList方法更新数据即可,性能更好:
private void SearchFilter(String text){ filteredList = new ArrayList<>(); for(FoodModel item: FoodList){ if(item.getFoodName().toLowerCase().contains(text.toLowerCase())){ filteredList.add(item); } } // 直接更新已有Adapter的列表,不用重新创建 foodAdapter.filteredList(filteredList); }
内容的提问来源于stack exchange,提问作者Danny
相关产品推荐
相关产品推荐

