显示空视图后,filter列表不再出现

出于某种原因,在显示没有匹配项目的空视图后,从搜索视图中删除所有文本后,我的列表视图将不会再次出现。

在我的适配器类中, .clear()中的AFAIK mData.clear(); 需要改变别的东西,但我不知道该怎么做。

ItemListAdapter类

 public class ItemListAdapter extends BaseAdapter implements Filterable { private List mData; private List mFilteredData; private LayoutInflater mInflater; private ItemFilter mFilter; public ItemListAdapter (List data, Context context) { mData = data; mFilteredData = new ArrayList(mData); mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public int getCount() { return mFilteredData.size(); } @Override public String getItem(int position) { return mFilteredData.get(position).getItem(); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = mInflater.inflate(R.layout.item_row, parent, false); holder = new ViewHolder(); holder.title = (TextView) convertView.findViewById(R.id.item_title); holder.description = (TextView) convertView.findViewById(R.id.item_description); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } holder.title.setText(mFilteredData.get(position).getItem()); holder.description.setText(mFilteredData.get(position).getItemDescription()); return convertView; } @Override public Filter getFilter() { if (mFilter == null) { mFilter = new ItemFilter(); } return mFilter; } /** * View holder */ static class ViewHolder { private TextView title; private TextView description; } /** * Filter for filtering list items */ /** * 

An array filter constrains the content of the array adapter with * a prefix. Each item that does not start with the supplied prefix * is removed from the list.

*/ private class ItemFilter extends Filter { @Override protected FilterResults performFiltering(CharSequence constraint) { FilterResults results = new FilterResults(); if (TextUtils.isEmpty(constraint)) { results.count = mData.size(); results.values = mData; } else { //Create a new list to filter on List resultList = new ArrayList(); for (Victoria str : mData) { if (str.getItemDescription().toLowerCase().contains(constraint.toString().toLowerCase())) { resultList.add(str); } } results.count = resultList.size(); results.values = resultList; } return results; } /** * Runs on ui thread * @param constraint the constraint used for the result * @param results the results to display */ @SuppressWarnings("unchecked") @Override protected void publishResults(CharSequence constraint, FilterResults results) { if (results.count == 0) { //Make list invisible //Make text view visible mFilteredData.clear(); notifyDataSetInvalidated(); } else { mFilteredData = (ArrayList)results.values; notifyDataSetChanged(); } } } }

在过滤之前 在此处输入图像描述

使用无效字符过滤后 在此处输入图像描述

清除搜索视图并尝试再次显示列表后 在此处输入图像描述

几个小修复应该让事情适合你。 首先, mDatamFilteredData数据应始终是两个不同的实例。 在构造函数中,让mFilteredData成为从mData复制的新实例

 mFilteredData = new ArrayList(mData); 

此外,在Filter ,您需要将相应的代码更新为以下内容:

 if (TextUtils.isEmpty(constraint)) { results.count = mData.size(); results.values = new ArrayList(mData); } 

然后你的getView()方法应该从mFilteredData而不是mData 。 理想情况下, getView()方法应该使用getItem(position)方法来访问数据。 这样,如果您更改了访问数据的位置的实现细节,则不必记住单独更新getView()方法。

最后作为旁注,您的过滤代码仅起作用,因为适配器不会改变mFilteredDatamData 。 通常,必须大量synchronize过滤过程和适配器的其他部分,因为performFiltering()在后台线程上发生。 如果您计划在构建之后添加对修改适配器数据的支持,那么您将需要开始添加synchronized块。

您正在修改包含原始数据的数组,并且当de Adapter重新创建列表时,该数组没有数据。

正确的做法是创建原始数组的副本,并在每次过滤列表时返回副本作为结果,保持原始数据不变。 可以在ArrayAdapter实现中找到一个非常好的示例。 请在此处查看源代码。

我将在这里包含源代码的副本以防万一:

 /** * 

An array filter constrains the content of the array adapter with * a prefix. Each item that does not start with the supplied prefix * is removed from the list.

*/ private class ArrayFilter extends Filter { @Override protected FilterResults performFiltering(CharSequence prefix) { FilterResults results = new FilterResults(); if (mOriginalValues == null) { synchronized (mLock) { mOriginalValues = new ArrayList(mObjects); } } if (prefix == null || prefix.length() == 0) { ArrayList list; synchronized (mLock) { list = new ArrayList(mOriginalValues); } results.values = list; results.count = list.size(); } else { String prefixString = prefix.toString().toLowerCase(); ArrayList values; synchronized (mLock) { values = new ArrayList(mOriginalValues); } final int count = values.size(); final ArrayList newValues = new ArrayList(); for (int i = 0; i < count; i++) { final T value = values.get(i); final String valueText = value.toString().toLowerCase(); // First match against the whole, non-splitted value if (valueText.startsWith(prefixString)) { newValues.add(value); } else { final String[] words = valueText.split(" "); final int wordCount = words.length; // Start at index 0, in case valueText starts with space(s) for (int k = 0; k < wordCount; k++) { if (words[k].startsWith(prefixString)) { newValues.add(value); break; } } } } results.values = newValues; results.count = newValues.size(); } return results; } @Override protected void publishResults(CharSequence constraint, FilterResults results) { //noinspection unchecked mObjects = (List) results.values; if (results.count > 0) { notifyDataSetChanged(); } else { notifyDataSetInvalidated(); } }