过滤器不被ArrayAdapter子类调用

时间:2015-06-02 17:42:39

标签: android android-arrayadapter android-filterable

这似乎很容易。

我有一个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();
            }
        }
    }
}

1 个答案:

答案 0 :(得分:0)

它不起作用,因为如果要自定义它的过滤逻辑,则不应该继承ArrayAdapter。您需要使用BaseAdapter从头开始实现适配器。

基本上,ArrayAdapter在内部跟踪自己的对象列表。但是,您只更新子类中的对象列表。您还需要更新内部列表。否则适配器不知道更改。

还有其他问题。例如,performFiltering()方法在后台线程上执行。这意味着您需要同步对列表所做的任何更改。 ArrayAdapter已在内部执行此操作...并且您无法访问它使用的同步锁定对象...这使您无法安全地同步。

此外,您的过滤解决方案似乎没有提供解决方案,以便在清除过滤后将列表恢复到其原始状态。

您可以通过ArrayAdapter过滤here了解有关问题的详情。一般经验法则。使用ArrayAdapter时,请不要创建自己的列表来跟踪数据,也不要自定义过滤。或者,您可以使用AbsArrayAdapter之类的内容,就像ArrayAdapter一样,但可以为您定义过滤逻辑。