自定义ListView ArrayAdapter不显示过滤数据

时间:2015-05-25 12:00:01

标签: android listview android-arrayadapter

我使用自定义ArrayAdapter类在ListView中显示一些数据。我在Action Bar中有一个微调器,根据它的项目选择我想过滤数据并在列表视图中重新填充它。

目前,当我的活动加载时,数据显示正确,但是当我从微调器中选择任何项目时,ListView变空并且不显示任何数据,尽管操作栏仍然出现。

你能告诉我我做错了什么吗?

这是我的自定义ArrayAdapter类:

public class MyAdapter extends ArrayAdapter implements Filterable {

private ArrayList < ArrayList < String >> arrayList;    
private LayoutInflater theInflater;

public MyAdapter(Context context, ArrayList arrayList) {
    super(context, R.layout.row_layout, arrayList);
    this.arrayList = arrayList;

}


@Override
public View getView(int position, View convertView, ViewGroup parent) {


    theInflater = LayoutInflater.from(getContext());

    View theView = theInflater.inflate(R.layout.row_layout, parent, false);

    ArrayList < String > values = (ArrayList < String > ) getItem(position);

    TextView a= (TextView) theView.findViewById(R.id.a);
    TextView b= (TextView) theView.findViewById(R.id.b);
    TextView c= (TextView) theView.findViewById(R.id.c);

    a.setText(values.get(0));
    b.setText(values.get(1));
    c.setText(values.get(2));

    return theView;
}


public Filter geFilter() {

    Filter filter = new Filter() {@Override
        protected FilterResults performFiltering(CharSequence constraint) {

            FilterResults results = new FilterResults();

            ArrayList al = new ArrayList();
            al.add("ValueA1");
            al.add("ValueA2");
            al.add("ValueA3");

            ArrayList bl = new ArrayList();
            bl.add("ValueB1");
            bl.add("ValueB2");
            bl.add("ValueB3");

            ArrayList < ArrayList < String >> array = new ArrayList < > ();

            array.add(al);
            array.add(bl);

            results.count = array.size();
            results.values = array;

            return results;

        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {


            arrayList = (ArrayList) results.values;

            notifyDataSetChanged();
        }
    };
    return filter;
 }

}

在Spinner的项目选择的监听器中,我有:

theAdapter.getFilter().filter("Incoming");

2 个答案:

答案 0 :(得分:1)

不幸的是,你的适配器出现了很多问题。例如没有实施ViewHolder paradigm。请注意,这不是您遇到问题的原因。但它确实解决了您的解决方案将产生的性能问题。

过滤本身不起作用,因为ArrayAdapter跟踪它自己的内部数据列表。 ArrayAdapter不保证您在外部跟踪的列表是相同的。在过滤操作期间尤其如此。您可以详细了解跟踪外部列表的危险,例如here

您的Filter非常有问题。

  1. 它会将您的外部数据列表重新分配到新列表,这意味着您的arrayList不再与内部ArrayAdapter正在跟踪的ArrayList相同。这会在您改变适配器时导致问题。
  2. 就目前而言,您的实现似乎并未实际过滤任何内容。通常,您还需要第二个performFiltering(),以便在过滤开始之前跟踪原始数据。否则,无法恢复过滤掉的数据。
  3. arrayList发生在后台线程上。虽然您在此方法期间似乎不访问ArrayAdapter(这是实际过滤数据的唯一方法),但您需要确保所有列表修改都已同步。 arrayList本身已处理同步,但无法将外部publishResults()与其同步。这意味着您无法在不冒并发修改错误的情况下编写过滤器。
  4. results.count == 0notifyDataSetInvalidated(),您必须results.count > 0。如果notifyDataSetChanged(),您必须ArrayAdapter
  5. Filterable已实施ArrayAdapter。将其添加到自定义适配器是多余的。
  6. ArrayAdapter拥有可过滤的实现存在一些错误。这里是a piece,它讨论了问题以及如何解决它。相关性是它讨论了如何创建自己的可过滤逻辑来解决问题。简而言之,您无法使用BaseAdapter创建自己的自定义过滤器。您需要使用data = {"name": "chan", "age", "35"}; 从头开始创建自己的适配器。

    或者,您可以使用third party library,它提供了一种非常简单的方法来实现您自己的自定义过滤逻辑。我强烈建议你去看那个人。另外,我强烈建议您更多地了解Google如何正确创建自定义适配器。他们有很多东西,你需要学习很多东西,从头开始正确实施。

答案 1 :(得分:0)

publishResults()方法中执行以下操作:

清除列表,再次添加结果数据并再次调用notifyDataSetInvalidated()

@Override
protected void publishResults(CharSequence constraint, FilterResults results) {

     arrayList = (ArrayList) results.values;
     notifyDataSetChanged();

     clear();
     for(int i = 0, l = arrayList.size(); i < l; i++) {
            add(arrayList.get(i));
     }
     notifyDataSetInvalidated(); 
 }