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

Android中EditText过滤ListView不更新问题求助

问题:Android中EditText过滤ListView不更新显示

我在Android中使用EditText过滤ListView组件,在TextWatcher的afterTextChanged方法中执行了如下代码:

cardBoxListViewAdapter.getFilter().filter(editable);

自定义Adapter代码如下:

public class CardBoxListViewAdapter extends ArrayAdapter<CardBoxItems> implements Filterable {

    private static final String TAG = "CardBoxListAdapter";

    private ValueFilter valueFilter;
    ArrayList<CardBoxItems> cardBoxModelArrayList;
    ArrayList<CardBoxItems> cardBoxModelArrayList2;
    private Context context;

    public CardBoxListViewAdapter(Context context, ArrayList<CardBoxItems> cardBoxModelArrayList) {
        super(context, 0, cardBoxModelArrayList);
        this.cardBoxModelArrayList = cardBoxModelArrayList;
        this.cardBoxModelArrayList2 = cardBoxModelArrayList;
        this.context = context;

        getFilter();
    }

    @Override
    public View getView(int position, View view, ViewGroup parent) {

        final CardBoxItems cardBoxModel = getItem(position);

        if (view == null) {
            view = LayoutInflater.from(getContext()).inflate(R.layout.adapter_listview_cardbox, parent, false);

        }

        TextView searchedFor = view.findViewById(R.id.cardBoxTitle);
        String searchedForString = cardBoxModel.getSearchedFor().replace("+", " ");
        searchedFor.setText(searchedForString);


        return view;

    }

    @Override
    public Filter getFilter() {
        if (valueFilter == null) {
            valueFilter = new ValueFilter();
        }
        return valueFilter;
    }

    private class ValueFilter extends Filter {

        @Override
        protected FilterResults performFiltering(CharSequence charSequence) {
            FilterResults results = new FilterResults();
            if (charSequence != null && charSequence.length() > 0) {
                ArrayList<CardBoxItems> filteredList = new ArrayList<>();
                for (int i = 0; i < cardBoxModelArrayList.size(); i++) {
                    if (cardBoxModelArrayList.get(i).getSearchedFor().toLowerCase().contains(charSequence.toString().toLowerCase())) {
                        filteredList.add(cardBoxModelArrayList.get(i));
                    }
                }
                results.count = filteredList.size();
                results.values = filteredList;
            } else {
                results.count = cardBoxModelArrayList.size();
                results.values = cardBoxModelArrayList;
            }
            return results;
        }

        @Override
        protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
            cardBoxModelArrayList2 = (ArrayList<CardBoxItems>) filterResults.values;
            System.out.println(cardBoxModelArrayList2.size());
            notifyDataSetChanged();
        }
    }

}

当前问题:控制台打印的列表长度正确,但ListView本身没有更新显示。已创建第二个ArrayList存储过滤后的信息,但问题仍未解决。


问题排查与解决方案

核心问题

你继承了ArrayAdapter,但过滤后仅更新了自定义的cardBoxModelArrayList2,而getView中调用的getItem(position)是从ArrayAdapter内部维护的数据源获取数据,并未同步更新;同时getCount方法默认返回ArrayAdapter数据源的大小,导致ListView无法感知过滤后的集合长度变化。

修复步骤

  1. 区分原始数据与过滤数据的引用
    构造方法中直接赋值会导致多个变量指向同一个集合,需创建集合副本:

    public CardBoxListViewAdapter(Context context, ArrayList<CardBoxItems> cardBoxModelArrayList) {
        super(context, 0, new ArrayList<>(cardBoxModelArrayList));
        this.cardBoxModelArrayList = new ArrayList<>(cardBoxModelArrayList); // 保存原始完整数据
        this.cardBoxModelArrayList2 = new ArrayList<>(cardBoxModelArrayList); // 初始化过滤数据
        this.context = context;
    }
    
  2. 修改getView从过滤集合取数据
    替换getItem(position)为自定义过滤集合的获取方式:

    @Override
    public View getView(int position, View view, ViewGroup parent) {
        final CardBoxItems cardBoxModel = cardBoxModelArrayList2.get(position); // 从过滤后的集合取数据
        if (view == null) {
            view = LayoutInflater.from(getContext()).inflate(R.layout.adapter_listview_cardbox, parent, false);
        }
        TextView searchedFor = view.findViewById(R.id.cardBoxTitle);
        String searchedForString = cardBoxModel.getSearchedFor().replace("+", " ");
        searchedFor.setText(searchedForString);
        return view;
    }
    
  3. 重写getCount方法返回过滤集合大小
    让ListView知道当前要显示的项数:

    @Override
    public int getCount() {
        return cardBoxModelArrayList2.size();
    }
    
  4. 可选:重写getItem方法(若有其他地方调用)
    如果代码中有其他地方调用getItem,也需要同步修改:

    @Override
    public CardBoxItems getItem(int position) {
        return cardBoxModelArrayList2.get(position);
    }
    

完成以上修改后,过滤操作会正确更新ListView的显示内容,因为现在Adapter的数据源完全由你维护的cardBoxModelArrayList2控制,notifyDataSetChanged会触发ListView重新加载数据。


内容的提问来源于stack exchange,提问作者newPHPDev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 11:35:02