Android中SearchView无法更新RecyclerView问题求助
Android SearchView过滤后RecyclerView不更新问题排查与修复
问题现象
在Android应用中使用SearchView实现搜索功能,onQueryTextChange方法已通过Log和Toast确认能根据输入完成数据过滤,但RecyclerView无法展示过滤后的结果。
核心问题分析
Adapter实例重复创建导致引用丢失
在Dialog初始化代码中,先给全局adapter赋值并绑定到RecyclerView,随后又创建了一个局部adapter实例,后续调用getFilter()时实际操作的是这个空数据的局部实例,而非绑定到RecyclerView的有效实例。Filter实现中的错误操作
performFiltering方法运行在后台线程,却直接修改了原始数据源dataList,还调用了只能在主线程执行的notifyDataSetChanged(),同时构造方法中直接让dataListFiltered指向dataList的引用,导致过滤操作会污染原始数据。
修正后的代码
1. 修复Dialog中的Adapter实例问题
editText1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ArrayList<addAccount> dataholder = new ArrayList<>(); final Dialog dialog = new Dialog(BillEntry.this); dialog.setContentView(R.layout.searchable_list_dialog); dialog.setTitle("Title"); DisplayMetrics displayMetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); int height = (int) (displayMetrics.heightPixels * 0.4); int width = (int) (displayMetrics.widthPixels * 0.9); dialog.getWindow().setLayout(width, height); dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.WHITE)); dialog.show(); recyclerView = dialog.findViewById(R.id.listItems); LinearLayoutManager layoutManager = new LinearLayoutManager(dialog.getContext()); recyclerView.setLayoutManager(layoutManager); // 仅创建一次adapter并绑定到RecyclerView adapter = new billEntryDialog(accounts); recyclerView.setAdapter(adapter); // 移除错误的局部adapter创建代码 // billEntryDialog adapter = new billEntryDialog(dataholder); displayAccountsFromJson(jsonData); SearchView search = dialog.findViewById(R.id.search); search.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { return false; } @Override public boolean onQueryTextChange(String newText) { adapter.getFilter().filter(newText); return true; } }); Button btnclosedialog = dialog.findViewById(R.id.btnClose); btnclosedialog.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(getApplicationContext(), "Closed", Toast.LENGTH_SHORT).show(); dialog.dismiss(); } }); } });
2. 修复Adapter的Filter实现与数据源初始化
public class billEntryDialog extends RecyclerView.Adapter<billEntryDialog.ViewHolder> implements Filterable { private ArrayList<addAccount> dataList; private ArrayList<addAccount> dataListFiltered; private FilterListener filterListener; public interface FilterListener { void onFilter(String query); } public billEntryDialog(ArrayList<addAccount> data) { // 复制原始数据,避免引用传递导致的数据源污染 this.dataList = new ArrayList<>(data); this.dataListFiltered = new ArrayList<>(data); } public void updatelist(ArrayList<addAccount> temp){ this.dataList = new ArrayList<>(temp); this.dataListFiltered = new ArrayList<>(temp); notifyDataSetChanged(); } public void setFilterListener(FilterListener listener) { this.filterListener = listener; } @NonNull @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_entry_account, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { addAccount data = dataListFiltered.get(position); holder.textView.setText(data.getEdtAccountName()); holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (filterListener != null) { filterListener.onFilter(data.getEdtAccountName()); } } }); } @Override public int getItemCount() { return dataListFiltered.size(); } @Override public Filter getFilter() { return new Filter() { @Override protected FilterResults performFiltering(CharSequence constraint) { String query = constraint.toString().toLowerCase(); ArrayList<addAccount> tempFilteredList = new ArrayList<>(); if (query.isEmpty()) { tempFilteredList.addAll(dataList); } else { for (addAccount item : dataList) { if (item.getEdtAccountName().toLowerCase().contains(query)) { tempFilteredList.add(item); } } } FilterResults filterResults = new FilterResults(); filterResults.values = tempFilteredList; return filterResults; } @Override protected void publishResults(CharSequence constraint, FilterResults results) { dataListFiltered.clear(); dataListFiltered.addAll((List<addAccount>) results.values); // publishResults运行在主线程,可安全调用notifyDataSetChanged notifyDataSetChanged(); } }; } static class ViewHolder extends RecyclerView.ViewHolder { TextView textView; ViewHolder(@NonNull View itemView) { super(itemView); textView = itemView.findViewById(R.id.txtName); } } }
内容的提问来源于stack exchange,提问作者Rahul Nakum
相关产品推荐
相关产品推荐

