You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中SearchView无法更新RecyclerView问题求助

Android SearchView过滤后RecyclerView不更新问题排查与修复

问题现象

在Android应用中使用SearchView实现搜索功能,onQueryTextChange方法已通过Log和Toast确认能根据输入完成数据过滤,但RecyclerView无法展示过滤后的结果。

核心问题分析

  1. Adapter实例重复创建导致引用丢失
    在Dialog初始化代码中,先给全局adapter赋值并绑定到RecyclerView,随后又创建了一个局部adapter实例,后续调用getFilter()时实际操作的是这个空数据的局部实例,而非绑定到RecyclerView的有效实例。

  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 19:45:54