【发布时间】:2014-04-02 15:40:56
【问题描述】:
在ArrayAdapter<T> 子类上使用自定义过滤器时,我总是会得到容器ListView 在运行时显示所有元素,然后再显示实际的过滤列表。
当用户使用SearchView/TextView 进行过滤并且需要调用过滤器事件onQueryTextChange 时,这对用户体验尤其不利,这使得过滤器似乎在每次按键时都会重置。
我的实现通常是这样的:
public class FilterAdapter extends ArrayAdapter<ListElement> {
private Context mContext;
public List<ListElement> listElements;
...
@Override
public Filter getFilter(){
return new Filter(){
@Override
protected FilterResults performFiltering(CharSequence constraint) {
Locale currentLocale = mContext.getResources().getConfiguration().locale;
constraint = constraint.toString().toLowerCase(currentLocale);
FilterResults results = new FilterResults();
if (constraint == null || constraint.length() == 0) {
//get a COPY of the original elements array not to change it by reference
results.values = new ArrayList<ListElement>(FilterAdapter.this.listElements);
results.count = listElements.size();
}
else{
List<ListElement> found = new ArrayList<ListElement>();
for(ListElement item : FilterAdapter.this.listElements){
if(item.filterString().toLowerCase(currentLocale).contains(constraint)){
found.add(item); //no need to create a copy of single element
}
}
results.values = found;
results.count = found.size();
}
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
clear();
for (ListElement item : (List<ListElement>) results.values) {
add(item);
}
notifyDataSetChanged();
}
};
}
据我了解,Filter.performFiltering 是 AsyncTask 的子类(或者至少在自己的线程中运行,从未真正去 AOSP 进行检查),而 Filter.publishResults 只是适配器 UI 线程的处理程序。
我见过的每个过滤器实现都倾向于在 publishResults 的开头和结尾调用 ArrayList.clear() 和 ArrayList.notifyDataSetChanged,而且我从来没有让过滤器在没有 clear+notify 的情况下工作......虽然我很漂亮
有什么技巧可以消除第二次重置的那一小部分,然后一次性从一个过滤列表转到另一个过滤列表?
【问题讨论】:
标签: android listview adapter android-arrayadapter