无法访问RecyclerView.Adapter中的public void filter方法求助
嘿,咱们来一步步解决你遇到的问题——首先搞定无法调用filter方法的问题,顺便还得修复你这个方法里的逻辑bug,不然就算能调用也没法正常工作~
解决RecyclerView.Adapter的filter方法无法调用的问题
首先,你在Activity里访问不到public的filter方法,大概率是这几个原因之一,咱们逐个排查:
1. 适配器的声明类型不对
如果你在Activity里把适配器声明成了父类RecyclerView.Adapter,而不是你自己写的那个子类(比如MyAppAdapter),编译器根本不知道你加了filter这个方法。
举个反例:
// 错误:用父类类型声明,只能调用RecyclerView.Adapter自带的方法 RecyclerView.Adapter adapter = new MyAppAdapter(initialData);
正确的做法是用你自定义的Adapter子类来声明:
// 正确:用自己的Adapter类声明,就能访问自定义的filter方法 MyAppAdapter mAdapter = new MyAppAdapter(initialData); recyclerView.setAdapter(mAdapter);
2. 适配器是局部变量,内部类访问不到
如果你的适配器是在onCreate或者某个方法里创建的局部变量,那OnQueryTextListener这个匿名内部类是拿不到它的。
解决办法很简单:把适配器改成Activity的成员变量,比如:
public class YourMainActivity extends AppCompatActivity { // 把适配器声明为Activity的成员变量 private MyAppAdapter mAppAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 初始化RecyclerView和数据 RecyclerView recyclerView = findViewById(R.id.your_recycler_view); List<AppInfo> originalData = getYourAppData(); // 你的数据初始化方法 mAppAdapter = new MyAppAdapter(originalData); recyclerView.setAdapter(mAppAdapter); // 初始化SearchView SearchView searchView = findViewById(R.id.search_view); searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { // 现在就能直接调用mAppAdapter的filter方法了 mAppAdapter.filter(query); return true; } @Override public boolean onQueryTextChange(String newText) { // 建议在这里也调用filter,实现实时搜索效果 mAppAdapter.filter(newText); return true; } }); } }
3. 适配器类的访问权限问题
确保你的自定义Adapter类是public修饰的,或者和你的Activity在同一个包下(默认的包访问权限也能行),不然Activity也没法访问它的public方法。
必须修复的filter方法逻辑bug
另外,我一眼就看到你写的filter方法有个致命问题——你清空了mDataSet之后,又去遍历它或者addAll它,这根本得不到任何数据啊!
错误的逻辑:
public void filter(String text) { mDataSet.clear(); if(text.isEmpty()){ // mDataSet已经被清空了,addAll自己等于啥都没加 mDataSet.addAll(mDataSet); } else{ text = text.toLowerCase(); // 遍历已经空了的mDataSet,根本找不到符合条件的项 for(AppInfo item: mDataSet){ if(item.getAppName().toLowerCase().contains(text)){ mDataSet.add(item); } } } notifyDataSetChanged(); }
正确的做法是保存一份原始的完整数据集,过滤的时候从原始数据里筛选,而不是直接操作显示用的数据集:
public class MyAppAdapter extends RecyclerView.Adapter<MyAppAdapter.ViewHolder> { // 用来显示的数据集,会随搜索内容变化 private List<AppInfo> mDisplayList; // 保存原始的完整数据,永远不变,用于过滤 private List<AppInfo> mOriginalList; // 构造方法里初始化两个列表 public MyAppAdapter(List<AppInfo> dataList) { mOriginalList = new ArrayList<>(dataList); mDisplayList = new ArrayList<>(dataList); } public void filter(String text) { mDisplayList.clear(); if(text.isEmpty()){ // 搜索为空时,显示全部原始数据 mDisplayList.addAll(mOriginalList); } else{ String lowerCaseText = text.toLowerCase(); // 遍历原始数据集,筛选符合条件的项 for(AppInfo item : mOriginalList){ if(item.getAppName().toLowerCase().contains(lowerCaseText)){ mDisplayList.add(item); } } } // 通知RecyclerView更新数据 notifyDataSetChanged(); } // 注意:后续所有和数据相关的方法都要用mDisplayList! @Override public int getItemCount() { return mDisplayList.size(); } @Override public void onBindViewHolder(ViewHolder holder, int position) { AppInfo currentApp = mDisplayList.get(position); // 绑定数据到UI上... } // 你的ViewHolder类... public static class ViewHolder extends RecyclerView.ViewHolder { // ... } }
这样修改之后,不仅能正常调用filter方法,搜索过滤的功能也能正常工作啦!
内容的提问来源于stack exchange,提问作者ClassA
相关产品推荐
相关产品推荐

