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

Android中AutoCompleteTextView未调用getView()方法问题求助

解决AutoCompleteTextView自定义Adapter中getView()不调用的问题

让我来帮你排查这个问题——你遇到的getView()始终不执行的情况,大概率是Adapter的数据同步逻辑或者Filter实现有问题。我仔细看了你的代码,发现了几个关键问题,咱们一步步来修正:

1. 重写getCount()导致的数据不一致

你重写了getCount()方法,返回的是自己维护的cityList.size(),但在publishResults()里,你调用的clear()和add()操作的是ArrayAdapter内部默认维护的数据集(也就是构造方法传入的objects列表),并没有同步更新你自己的cityList。这就会出现一种矛盾:Filter执行后,内部数据集已经变化,但getCount()还是返回原来cityList的大小,AutoCompleteTextView判断没有可显示的item,自然不会调用getView()。

修正方案:

让cityList成为Adapter唯一的数据源,所有数据更新都基于它,同时调整publishResults()同步更新cityList:

@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
    cityList.clear();
    if (results != null && results.count > 0) {
        // 将过滤结果同步到cityList
        cityList.addAll((ArrayList<BusCityList>) results.values);
        // 所有数据更新完成后,再通知Adapter刷新
        notifyDataSetChanged();
    } else {
        // 无匹配结果时,通知Adapter数据失效
        notifyDataSetInvalidated();
    }
}

同时,你的getItem()和getCount()都是基于cityList的,这个保持不变即可。

2. 错误的notifyDataSetChanged()调用时机

你在publishResults()的for循环里,每添加一个item就调用一次notifyDataSetChanged(),这会导致Adapter多次刷新,不仅效率极低,还可能引发数据状态混乱。正确的做法是:所有数据更新完成后,只调用一次notifyDataSetChanged()(就像上面修正的那样)。

3. 检查AutoCompleteTextView的触发阈值

AutoCompleteTextView默认需要输入至少2个字符才会触发下拉提示,如果你的输入字符数不够,也不会调用getView()。可以在设置Adapter时添加阈值设置,测试是否是这个原因:

AutoCompleteTextView txtToWhere = (AutoCompleteTextView) v.findViewById(R.id.txtToWhere);
busCityListAdapter = new BusCityListAdapter(getActivity(), arrayList);
txtToWhere.setAdapter(busCityListAdapter);
// 设置输入1个字符就触发下拉提示
txtToWhere.setThreshold(1);
busCityListAdapter.notifyDataSetChanged();

4. Filter的空输入逻辑优化

在performFiltering()的else分支,你返回了一个空的FilterResults,这会导致当输入为空时,没有任何数据显示。建议在这种情况下返回完整的原始数据集:

@Override
protected FilterResults performFiltering(CharSequence constraint) {
    FilterResults filterResults = new FilterResults();
    if (constraint != null && constraint.length() > 0) {
        suggestionsList.clear();
        String lowerConstraint = constraint.toString().toLowerCase();
        for (BusCityList city : tempCityList) {
            if (city.getCity_name().toLowerCase().startsWith(lowerConstraint)) {
                suggestionsList.add(city);
            }
        }
        filterResults.values = suggestionsList;
        filterResults.count = suggestionsList.size();
    } else {
        // 输入为空时,返回完整的原始城市列表
        filterResults.values = tempCityList;
        filterResults.count = tempCityList.size();
    }
    return filterResults;
}

最后,修改后的完整Adapter代码

public class BusCityListAdapter extends ArrayAdapter<BusCityList> {
    private ArrayList<BusCityList> cityList;
    private ArrayList<BusCityList> tempCityList;
    private ArrayList<BusCityList> suggestionsList;

    public BusCityListAdapter(Context context, ArrayList<BusCityList> objects) {
        super(context, android.R.layout.simple_list_item_1, objects);
        this.cityList = objects;
        this.tempCityList = new ArrayList<>(objects);
        this.suggestionsList = new ArrayList<>();
    }

    @Override
    public int getCount() {
        System.out.println("Main List Size=="+cityList.size());
        return cityList.size();
    }

    @Override
    public BusCityList getItem(int position) {
        return cityList.get(position);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        System.out.println("Inside GetView");
        BusCityList busCity = getItem(position);
        if (convertView == null) {
            convertView = LayoutInflater.from(getContext()).inflate(R.layout.bus_city_name_layout, parent, false);
        }
        MyTextView bus_name_label = convertView.findViewById(R.id.bus_name_label);
        if (bus_name_label != null) {
            bus_name_label.setText(busCity.getCity_name());
        }
        return convertView;
    }

    @Override
    public Filter getFilter() {
        return myFilter;
    }

    Filter myFilter = new Filter() {
        @Override
        public CharSequence convertResultToString(Object resultValue) {
            BusCityList busCity = (BusCityList) resultValue;
            return busCity.getCity_name();
        }

        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults filterResults = new FilterResults();
            if (constraint != null && constraint.length() > 0) {
                suggestionsList.clear();
                String lowerConstraint = constraint.toString().toLowerCase();
                for (BusCityList city : tempCityList) {
                    if (city.getCity_name().toLowerCase().startsWith(lowerConstraint)) {
                        suggestionsList.add(city);
                    }
                }
                filterResults.values = suggestionsList;
                filterResults.count = suggestionsList.size();
            } else {
                filterResults.values = tempCityList;
                filterResults.count = tempCityList.size();
            }
            return filterResults;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            cityList.clear();
            if (results != null && results.count > 0) {
                cityList.addAll((ArrayList<BusCityList>) results.values);
                notifyDataSetChanged();
            } else {
                notifyDataSetInvalidated();
            }
        }
    };
}

按照上面的修改后,再测试输入字符,应该就能正常触发getView()方法了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 09:37:42