【问题标题】:filter not being invoked by ArrayAdapter sub-classArrayAdapter 子类未调用过滤器
【发布时间】:2023-03-24 06:22:01
【问题描述】:

看来这应该很容易。

我有一个使用 ArrayAdapter 的带有列表的 Android 应用程序。有用。我用自定义子类替换了 ArrayAdapter。有用。我添加了一个内部类,它是 Filter 的子类,并将 ArrayAdaptor 子类标记为实现 Fiterable。它工作正常,只是它不过滤。

我要在这里说什么神奇的词?

过滤器子类中的任何方法都没有被调用。

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();
            }
        }
    }
}

【问题讨论】:

  • 我现在使用的是 SimpleCursorAdaptor。反正这里没有答案,所以……啦。

标签: android android-arrayadapter android-filterable


【解决方案1】:

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

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

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

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

您可以阅读更多关于ArrayAdapter 过滤here 的问题。一般经验法则。使用ArrayAdapter 时不要创建自己的列表来跟踪数据,也不要自定义过滤。或者,您可以使用类似于 ArrayAdapterAbsArrayAdapter 之类的东西,但您可以为自己定义过滤逻辑。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多