Android中AutoCompleteTextView未调用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

