这似乎很容易。
我有一个Android应用程序,其中包含使用ArrayAdapter的列表。有用。我将ArrayAdapter替换为自定义子类。有用。我添加了一个内部类,它是Filter的一个子类,并将ArrayAdaptor子类标记为实现Fiterable。它工作正常,但它不会过滤。
我在这里说的神奇话语是什么?
没有调用Filter子类中的任何方法。
public class XYZListAdapter extends ArrayAdapter<XYZListFragment.XYZItem> implements Filterable {
private List<XYZListFragment.XYZItem> sourceObjects;
private Context sourceContext;
private XYZFilter xyzFilter;
public XYZListAdapter(Context context, int resource, int textViewResourceId, List<XYZListFragment.XYZItem> objects) {
super(context, resource, textViewResourceId, objects);
sourceObjects = new ArrayList<>(objects);
sourceContext = context;
}
public View getView(int position, View convertView, ViewGroup parent) {
Log.i("XYZAdapter", "getView");
View v = convertView;
if (v == null) {
v = ((LayoutInflater)sourceContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.fragment_xyz_list_item, parent, false);
}
XYZListFragment.XYZItem mItem = sourceObjects.get(position);
if (mItem != null) {
TextView t = (TextView)v.findViewById(R.id.xyz_list_item_name_view);
if (t != null) {
t.setText(mItem.name());
}
}
return v;
}
@Override
public Filter getFilter() {
Log.i("XYZAdapter", "getFilter");
if (xyzFilter == null)
xyzFilter = new XYZFilter();
return xyzFilter;
}
private class XYZFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
Log.i("XYZFilter", "perform");
FilterResults results = new FilterResults();
if (constraint == null || constraint.length() == 0) {
results.values = sourceObjects;
results.count = sourceObjects.size();
}
else {
List<XYZListFragment.XYZItem> nextXYZList = new ArrayList<>();
for (XYZListFragment.XYZItem p : sourceObjects) {
if (p.name().toUpperCase().startsWith(constraint.toString().toUpperCase()))
nextXYZList.add(p);
}
results.values = nextXYZList;
results.count = nextXYZList.size();
}
return results;
}
@Override
@SuppressWarnings("unchecked")
protected void publishResults(CharSequence constraint, FilterResults results) {
Log.i("XYZFilter", "publish");
if (results.count == 0)
notifyDataSetInvalidated();
else {
sourceObjects = (List<XYZListFragment.XYZItem>) results.values;
notifyDataSetChanged();
}
}
}
}
答案 0 :(得分:0)
它不起作用,因为如果要自定义它的过滤逻辑,则不应该继承ArrayAdapter
。您需要使用BaseAdapter
从头开始实现适配器。
基本上,ArrayAdapter
在内部跟踪自己的对象列表。但是,您只更新子类中的对象列表。您还需要更新内部列表。否则适配器不知道更改。
还有其他问题。例如,performFiltering()
方法在后台线程上执行。这意味着您需要同步对列表所做的任何更改。 ArrayAdapter
已在内部执行此操作...并且您无法访问它使用的同步锁定对象...这使您无法安全地同步。
此外,您的过滤解决方案似乎没有提供解决方案,以便在清除过滤后将列表恢复到其原始状态。
您可以通过ArrayAdapter
过滤here了解有关问题的详情。一般经验法则。使用ArrayAdapter
时,请不要创建自己的列表来跟踪数据,也不要自定义过滤。或者,您可以使用AbsArrayAdapter之类的内容,就像ArrayAdapter
一样,但可以为您定义过滤逻辑。