【问题标题】:Custom filtering for Custom ArrayAdapter in ListViewListView 中自定义 ArrayAdapter 的自定义过滤
【发布时间】:2013-06-18 13:07:38
【问题描述】:

我自己写了一个这样的 ArrayAdapter:

public class PoiListAdapter extends ArrayAdapter<Poi> implements Filterable {

    private Context context;
    private final List<Poi> valuesPoi;
    private ItemsFilter mFilter;

    public PoiListAdapter(Context context, List<Poi> valuesPoi) {
        super(context, R.layout.poilist);
        this.context = context;
        this.valuesPoi = valuesPoi;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        View rowView = inflater.inflate(R.layout.poilist, parent, false);
        TextView textViewName = (TextView) rowView.findViewById(R.id.name_poi);
        TextView textViewDis = (TextView) rowView
                .findViewById(R.id.discrip_poi);
        textViewName.setText(valuesPoi.get(position).getName());
        textViewDis.setText(valuesPoi.get(position).getDiscription());
        return rowView;
    }

    /**
     * Implementing the Filterable interface.
     */
    public Filter getFilter() {
        if (mFilter == null) {
            mFilter = new ItemsFilter(this);
        }
        return mFilter;
    }

    public List<Poi> getValuesPoi() {
        return valuesPoi;
    }

    public void addValuesPoi(Poi p) {
        valuesPoi.add(p);
    }
      @Override
  public void clear() {
    valuesPoi.clear();
  }
}

对于这个适配器,我想实现一个搜索功能。因此我实现了一个自定义过滤器类:

public class ItemsFilter extends Filter {

private PoiListAdapter poiListAdapter;

public ItemsFilter(PoiListAdapter poiListAdapter) {
    this.poiListAdapter = poiListAdapter;
}

@Override
protected FilterResults performFiltering(CharSequence constraint) {
    constraint = constraint.toString().toLowerCase();
    FilterResults result = new FilterResults();
    ArrayList<Poi> filterList = new ArrayList<Poi>();
    if (constraint != null && constraint.toString().length() > 0) {
        ArrayList<Poi> orginalList = new ArrayList<Poi>(
                poiListAdapter.getValuesPoi());

        for (Poi p : orginalList) {
            if (p.getName().toLowerCase().contains(constraint))
                filterList.add(p);
        }
        Log.i("DEBUG", orginalList.toString());
        result.values = filterList;
        result.count = filterList.size();

    } else {

        result.values = poiListAdapter.getValuesPoi();
        result.count = poiListAdapter.getValuesPoi().size();

    }
    return result;
}

@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
    ArrayList<Poi> fitems = (ArrayList<Poi>) results.values;
    poiListAdapter.clear();
    for (Poi p : fitems) {
        poiListAdapter.addValuesPoi(p);
        poiListAdapter.notifyDataSetChanged();
    }
}

1. 问题

....是我得到了一个 java.util.concurrentmodificationexception:

for (Poi p : fitems) {
            poiListAdapter.addValuesPoi(p);
            poiListAdapter.notifyDataSetChanged();
        }

我认为问题在于我想修改访问权限下的 Arraylist。我想我必须使用同步,但我以前从未使用过它。

更新: 这个问题解决了!这里是代码:

for(Iterator<Poi> i = fitems.iterator(); i.hasNext();) {
        Poi p = i.next();
        poiListAdapter.addValuesPoi(p);
        //poiListAdapter.notifyDataSetChanged();
    }

2. 问题

列表视图在开始时是空的。一开始我想展示所有元素!通过搜索元素也不会显示任何内容! Listview 目前没有显示任何内容!

【问题讨论】:

  • 第一个问题解决了!

标签: android filter android-listview android-arrayadapter


【解决方案1】:

可以通过两种方式避免并发修改:

  1. poiListAdapter.addValuesPoi(p) 将此代码添加到同步方法中。同步方法不能同时访问。

  2. 使用 Collections.synchronizedList

【讨论】:

    【解决方案2】:

    for-each 循环在内部使用一个迭代器,并且在迭代时不能向集合中添加任何内容(这就是异常的原因)。尝试创建 ArrayList 的新实例并对其进行交互

    @SuppressWarnings("unchecked")
    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {
        ArrayList<Poi> fitems = new ArrayList((ArrayList<Poi>) results.values);
        poiListAdapter.clear();
        for (Poi p : fitems) {
            poiListAdapter.addValuesPoi(p);
            poiListAdapter.notifyDataSetChanged();
        }
    }
    

    for-each 类似于:

    for(Iterator<Poi> i = fitms.iterator(); i.hasNext(); ) {
      Poi item = i.next();    
    }
    

    问题 2:

    列表一开始是空的,可能是因为你提交的数据集是空的

    【讨论】:

      【解决方案3】:

      @JavaNullPointer:我遇到了和你一样的问题。我尝试实现此处提供的解决方案,但遇到了不同类型的问题。经过一段时间的思考,我认为默认的过滤器可能正在使用对象的 toString() 方法进行过滤……这转向了我。它为我省去了很多麻烦..

      阅读您的代码,我相信您想按 Poi 类的名称字段进行过滤。如果是这样,那么快速的解决方案是 解决方案:

      public class Poi{
      
      //your constructors and methods
      
      @Override
      public String toString(){
         return getName(); 
      }
      

      【讨论】:

        【解决方案4】:

        我可以解决我的问题。这是我的解决方案!

            package hsos.ds.helper;
        
        import hsos.ds.db.Poi;
        
        import java.util.ArrayList;
        import java.util.List;
        import android.widget.Filter;
        
        public class ItemsFilter extends Filter {
        
            private PoiListAdapter poiAdapter;
            private List<Poi> valuesPoi;
            private List<Poi> filteredPoi;
        
            public ItemsFilter(PoiListAdapter _poiAdapter) {
                this.poiAdapter = _poiAdapter;
                this.valuesPoi = poiAdapter.getValuesPoi();
                this.filteredPoi = poiAdapter.getFilteredPoi();
            }
        
            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                FilterResults result = new FilterResults();
                constraint = constraint.toString().toLowerCase();
        
                if (constraint == null || constraint.length() == 0) {
                    ArrayList<Poi> list = new ArrayList<Poi>(valuesPoi);
                    result.values = valuesPoi;
                    result.count = valuesPoi.size();
        
                } else {
                    final ArrayList<Poi> orginalList = new ArrayList<Poi>(valuesPoi);
                    final ArrayList<Poi> filterList = new ArrayList<Poi>();
                    int count = orginalList.size();
                    for (int i = 0; i < count; i++) {
                        final Poi p = orginalList.get(i);
                        if (p.getName().toLowerCase().contains(constraint))
                            filterList.add(p);
                    }
                    result.values = filterList;
                    result.count = filterList.size();
                }
                return result;
            }
        
            @SuppressWarnings("unchecked")
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                filteredPoi = (List<Poi>) results.values;
                poiAdapter.notifyDataSetChanged();
                poiAdapter.clear();
                int count = filteredPoi.size();
                for (int i = 0; i < count; i++) {
                    poiAdapter.add(filteredPoi.get(i));
                    poiAdapter.notifyDataSetInvalidated();
                }
            }
        }
        

        和适配器:

        公共类 PoiListAdapter 扩展 ArrayAdapter 实现 Filterable {

        private List<Poi> valuesPoi;
        private List<Poi> filteredPoi;
        private ItemsFilter mFilter;
        
        public PoiListAdapter(Context context, List<Poi> valuesPoi) {
            super(context, R.layout.poilist);
            this.valuesPoi = new ArrayList<Poi>(valuesPoi);
            this.filteredPoi = new ArrayList<Poi>(valuesPoi);
            this.mFilter = new ItemsFilter(this);
        }
        
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View v = convertView;
            if (v == null) {
                LayoutInflater vi = (LayoutInflater) getContext().getSystemService(
                        Context.LAYOUT_INFLATER_SERVICE);
                v = vi.inflate(R.layout.poilist, null);
            }
        
            Poi p = filteredPoi.get(position);
        
            if (p != null) {
                TextView tt = (TextView) v.findViewById(R.id.name_poi);
                TextView bt = (TextView) v.findViewById(R.id.discrip_poi);
                if (tt != null) {
                    tt.setText(p.getName());
                }
                if (bt != null) {
                    bt.setText(p.getDiscription());
                }
            }
            return v;
        }
        
        @Override
        public Filter getFilter() {
            if (mFilter == null) {
                mFilter = new ItemsFilter(this);
            }
            return mFilter;
        }
        
        public List<Poi> getValuesPoi() {
            return valuesPoi;
        }
        
        
        public List<Poi> getFilteredPoi() {
            return filteredPoi;
        
        }
        

        }

        为了显示完整列表onStart(),我在我的活动的onStart()-Method 中插入了一点“hack”,因为完整列表显示在输入之后:

        if(searchText!=null){
                searchText.setText(" ");
                searchText.setText("");
            }
        

        【讨论】:

        猜你喜欢
        • 2011-09-23
        • 2012-04-24
        • 2015-08-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多