2013-03-04 41 views
8

我是android的新手。过滤自定义适配器IndexOutOfBoundsException

我的自定义适配器过滤时会导致异常。

这是我的代码。 私有类DeptAdapter扩展ArrayAdapter实现的可筛选{

private ArrayList<Dept> items; 
    private ArrayList<Dept> mOriginalValues; 

    public DeptAdapter(Context context, int textViewResourceId, ArrayList<Dept> items) { 
      super(context, textViewResourceId, items); 
      this.items = items; 
    } 
    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     View v = convertView; 

     if (v == null) { 
      LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      v = vi.inflate(R.layout.item_listview_2line, null); 
     } 
     Dept d = items.get(position); 
     if (d != null) { 
       TextView tt = (TextView) v.findViewById(R.id.toptext); 
       TextView bt = (TextView) v.findViewById(R.id.bottomtext); 
       if (tt != null){ 
        tt.setText(d.dept_nm);        
       } 
       if(bt != null){ 
        bt.setText(d.dept_cd); 
       } 
     } 
     return v; 
    } 

    @Override 
    public Filter getFilter() { 
     Filter filter = new Filter() { 

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

       items = (ArrayList<Dept>) results.values; // has the filtered values 
       if (results.count > 0) { 
        notifyDataSetChanged(); 
       } else { 
        notifyDataSetInvalidated(); 
       } 
      } 

      } 
      @Override 
      protected FilterResults performFiltering(CharSequence constraint) { 
       FilterResults results = new FilterResults();  // Holds the results of a filtering operation in values 
       ArrayList<Dept> FilteredArrList = new ArrayList<Dept>(); 

       if (mOriginalValues == null) { 
        mOriginalValues = new ArrayList<Dept>(items); // saves the original data in mOriginalValues 
       } 

       if (constraint == null || constraint.length() == 0) { 

        // set the Original result to return 
        results.count = mOriginalValues.size(); 
        results.values = mOriginalValues; 
       } else { 
        constraint = constraint.toString().toLowerCase(); 
        for (int i = 0; i < mOriginalValues.size(); i++) { 
         Dept d = mOriginalValues.get(i); 
         if (d.dept_cd.toLowerCase().startsWith(constraint.toString()) || d.dept_nm.toLowerCase().startsWith(constraint.toString())) { 
          FilteredArrList.add(d); 
         } 
        } 
        // set the Filtered result to return 
        results.count = FilteredArrList.size(); 
        results.values = FilteredArrList; 
       } 
       return results; 
      } 
     }; 
     return filter; 
    } 
} 

class Dept 
{ 
    String dept_cd; 
    String dept_nm; 
    public Dept(String dept_cd, String dept_nm) 
    { 
     this.dept_cd = dept_cd; 
     this.dept_nm = dept_nm; 
    } 
    public String toString() 
    { 
     return this.dept_nm+ "(" + this.dept_cd +")" ; 
    } 
} 

帮助我的人.... 我不明白为什么getView()方法被调用更多的则items.size()记住

+0

请添加DeptAdapter类的logcat输出 – 2013-03-04 05:01:06

+1

的完整代码,我也希望这两种方法的代码getCount将()和的getItem(INT位置) – 2013-03-04 05:15:09

回答

16

保持这getView()会查询该superclass了,这对现在的项目的大小,就是你原来调用超类构造函数时,通过它

super(context, textViewResourceId, items); 

因此,超类在您过滤后不知道您已更改了大小。这意味着getCount()将返回数组的原始大小,这比您的过滤数组大得多。

这意味着所以你一定是您传回实际有效大小应覆盖getCount()方法:

@Override 
public int getCount() 
{ 
    return items.size(); 
} 

你也应该重写有关列表操作的其他方法(如获取)如果你打算使用它们。 如:

@Override 
public Dept getItem (int pos){ 
    return items.get(pos); 
} 
+1

非常感谢你!你的回答完全解决了我的问题。 – user1788012 2013-03-04 05:19:26

+1

保存我的整个一天 – Nabin 2014-08-18 08:09:45

+1

我遇到了同样的问题,您的解决方案也适用于我。谢谢! – user2151486 2014-09-05 11:03:26

0

你缺少getCount()方法, 看看这个demo

我希望这会有所帮助!

0
private ArrayList<Dept> items; 
    private ArrayList<Dept> mOriginalValues; 

    public DeptAdapter(Context context, int textViewResourceId, ArrayList<Dept> items) { 
      super(context, textViewResourceId, items); 
      this.items = items; 
      this.mOriginalValues=items; //add this line in your code 
    } 
+0

'mOriginalValues'是一个占位符,同时过滤到位。它不需要从一开始就坚持这些项目。 – 2013-03-04 05:18:16

+0

if(mOriginalValues == null){mOriginalValues = new ArrayList (items); //将原始数据保存在mOriginalValues中}您在这里看到的第一次使用,然后初始化bro @ A - C – QuokMoon 2013-03-04 05:21:44

+0

如果它是空的,那么它被初始化,并且这是您保存副本的位置。在构造函数中进行赋值是一种很好的自动保险功能,但当您为某个原因进行过滤时,“空”检查已经存在。 'this.mOriginalValues = items;'在构造函数中不需要。 – 2013-03-04 05:24:25

1

您需要添加此方法更好的性能:

 @Override 
     public int getCount() { 
      return items.size(); 
     } 

     @Override 
     public Object getItem(int position) { 
      return this.items.get(position); 
     } 

     @Override 
     public long getItemId(int position) { 
      return position; 
     }