过滤自定义适配器 IndexOutOfBoundsException。

8

我是一名Android的新手。

当我进行过滤操作时,我的自定义适配器会出现异常。

以下是我的代码: private class DeptAdapter extends ArrayAdapter implements Filterable {

    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()。


请添加DeptAdapter类的完整代码和logcat输出。 - Kirit Vaghela
1
我还想要两个方法getCount()和getItem(int position)的代码。 - Kirit Vaghela
4个回答

15
请记住,getView()将查询父类拥有的项目的大小,这是当您调用父类构造函数时传递给它的原始内容。保留HTML标签。
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
1
我也遇到了同样的问题,你的解决方案对我也起作用了。谢谢! - user2151486

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

0

你缺少了 getCount() 方法, 看一下这个 演示

希望对你有所帮助!


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
    }

mOriginalValues 是一个占位符,用于筛选过程中。它不需要一开始就保存所有项目。 - A--C
如果 (mOriginalValues == null) { mOriginalValues = new ArrayList<Dept>(items); // 将原始数据保存在mOriginalValues中 } 你看到这里先使用再初始化,兄弟 @A--C - QuokMoon
如果它为空,那么在那里进行初始化,并在那里保存副本。在构造函数中分配是一个很好的故障保护措施,但当您过滤原因时,null检查已经存在。在构造函数中不需要this.mOriginalValues=items; - A--C
看一下ArrayAdapter源代码。搜索init()mOriginalValues并没有从一开始就被实例化。因此,在构造函数中实例化该对象并不能起到太大的作用。 - A--C

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接