ListView 中自定义 ArrayAdapter 的自定义过滤
Posted
技术标签:
【中文标题】ListView 中自定义 ArrayAdapter 的自定义过滤【英文标题】:Custom filtering for Custom ArrayAdapter in ListView 【发布时间】: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 目前没有显示任何内容!
【问题讨论】:
第一个问题解决了! 【参考方案1】:可以通过两种方式避免并发修改:
poiListAdapter.addValuesPoi(p) 将此代码添加到同步方法中。同步方法不能同时访问。
使用 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("");
【讨论】:
知道如何解决这个问题吗? ***.com/questions/20524417/…以上是关于ListView 中自定义 ArrayAdapter 的自定义过滤的主要内容,如果未能解决你的问题,请参考以下文章
在AutocompleteTextview的下拉列表中自定义分隔符/分隔符