搜索过滤列表视图的Android IndexOutOfBoundsException错误

6

我在SherlockAction Bar的SearchView中实现了搜索过滤器。我实现了自定义过滤器,但是当我输入任何字母时出现了错误。

public class PlacesListAdapter extends ArrayAdapter<Place> implements
        Filterable {

    public Context mContext;

    List<Place> mPlaces, orig;

    public PlacesListAdapter(Context context, List<Place> places) {
        super(context, R.layout.list_item_places, places);
        // TODO Auto-generated constructor stub
        this.mPlaces = places;
        this.mContext = context;

        orig = new ArrayList<Place>(places);

    }

    @Override
    public Place getItem(int position) {
        // TODO Auto-generated method stub
        return mPlaces.get(position);
    }

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

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

        ViewHolder holder;

        if (convertView == null) {
            LayoutInflater viewInflater;
            viewInflater = LayoutInflater.from(getContext());
            convertView = viewInflater.inflate(R.layout.list_item_places, null);

            holder = new ViewHolder();
            holder.placeTitle = (TextView) convertView
                    .findViewById(R.id.place_title);
            holder.placeDistance = (TextView) convertView
                    .findViewById(R.id.place_distance);
            holder.placeCategoryIcon = (ImageView) convertView
                    .findViewById(R.id.place_category_icon);

            convertView.setTag(holder);

        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        holder.placeTitle.setText(mPlaces.get(position).getPlaceName());
        holder.placeDistance.setText(mPlaces.get(position).getPlaceDistance());
        holder.placeCategoryIcon
                .setImageResource(R.drawable.icon_category_hillstation);

        // // Setting Alternative Row Colors
        if (position % 2 == 0) {
            convertView
                    .setBackgroundResource(R.drawable.list_view_places_row_1);
        } else {
            convertView
                    .setBackgroundResource(R.drawable.list_view_places_row_2);
        }

        return convertView;
    }

    static class ViewHolder {
        TextView placeId;

        TextView placeTitle;

        TextView placeDistance;

        ImageView placeCategoryIcon;
    }

    @Override
    public Filter getFilter() {
        // TODO Auto-generated method stub
        return new PlaceFilter();
    }

    private class PlaceFilter extends Filter {

        @Override
        protected FilterResults performFiltering(CharSequence constraint){
            FilterResults oReturn = new FilterResults();
            ArrayList<Place> results = new ArrayList<Place>();
            if (orig == null)
                orig = mPlaces;
            if (constraint != null) {
                if (orig != null && orig.size() > 0) {
                    for (Place g : orig) {
                        if (g.getPlaceName()
                                .toLowerCase()
                                .startsWith(constraint.toString().toLowerCase()))
                            results.add(g);
                    }
                }
                oReturn.values = results;
            }
            return oReturn;
        }

        @Override
        protected void publishResults(CharSequence constraint,
                FilterResults results) {
            mPlaces = (ArrayList<Place>) results.values;
            notifyDataSetChanged();
        }

    }

}

错误

12-26 17:24:43.900: E/AndroidRuntime(18693): FATAL EXCEPTION: main
12-26 17:24:43.900: E/AndroidRuntime(18693): java.lang.IndexOutOfBoundsException: Invalid index 1, size is 1
12-26 17:24:43.900: E/AndroidRuntime(18693):    at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:251)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at java.util.ArrayList.get(ArrayList.java:304)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at com.m7.nomad.PlacesListAdapter.getView(PlacesListAdapter.java:68)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at android.widget.AbsListView.obtainView(AbsListView.java:2193)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at android.widget.ListView.makeAndAddView(ListView.java:1774)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at android.widget.ListView.fillDown(ListView.java:672)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at android.widget.ListView.fillSpecific(ListView.java:1330)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at android.widget.ListView.layoutChildren(ListView.java:1603)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at android.widget.AbsListView.onLayout(AbsListView.java:2044)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at android.view.View.layout(View.java:11418)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at android.view.ViewGroup.layout(ViewGroup.java:4224)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at android.widget.RelativeLayout.onLayout(RelativeLayout.java:925)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at android.view.View.layout(View.java:11418)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at android.view.ViewGroup.layout(ViewGroup.java:4224)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at android.widget.FrameLayout.onLayout(FrameLayout.java:431)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at android.view.View.layout(View.java:11418)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at android.view.ViewGroup.layout(ViewGroup.java:4224)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1628)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1486)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at android.widget.LinearLayout.onLayout(LinearLayout.java:1399)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at android.view.View.layout(View.java:11418)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at android.view.ViewGroup.layout(ViewGroup.java:4224)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at android.widget.FrameLayout.onLayout(FrameLayout.java:431)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at android.view.View.layout(View.java:11418)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at android.view.ViewGroup.layout(ViewGroup.java:4224)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1628)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2585)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at android.os.Handler.dispatchMessage(Handler.java:99)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at android.os.Looper.loop(Looper.java:137)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at android.app.ActivityThread.main(ActivityThread.java:4507)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at java.lang.reflect.Method.invokeNative(Native Method)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at java.lang.reflect.Method.invoke(Method.java:511)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
12-26 17:24:43.900: E/AndroidRuntime(18693):    at dalvik.system.NativeStart.main(Native Method)

错误

它指向的是

holder.placeTitle.setText(mPlaces.get(position).getPlaceName());
4个回答

2
尝试覆盖这一行
holder.placeTitle.setText(mPlaces.get(position).getPlaceName());

在以下情况下:
if(position < mPlaces.size() && holder.placeTitle != null)
  holder.placeTitle.setText(mPlaces.get(position).getPlaceName());

编辑:

这是我实现的小片段:

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

            ViewHolder holder;

            if (convertView == null) {
                LayoutInflater viewInflater;
                viewInflater = getLayoutInflater();
                convertView = viewInflater.inflate(R.layout.listview, null);

                holder = new ViewHolder();
                convertView.setTag(holder);

            } else {
                holder = (ViewHolder) convertView.getTag();

                // Try here first
                holder.textview = (TextView) convertView.findViewById(R.id.TextView01);
                holder.imageview = (ImageView) convertView.findViewById(R.id.ImageView01);
            }

            // Try here second
            // holder.textview = (TextView)convertView.findViewById(R.id.TextView01);
            // holder.imageview = (ImageView)convertView.findViewById(R.id.ImageView01);

            if (holder.textview != null && position < data_text.length)
                holder.textview.setText(data_text[position]);
            if (holder.imageview != null && position < data_image.length)
                holder.imageview.setImageResource(data_image[position]);

            return convertView;
        }

你可以用你自己的变量来替换它。
谢谢。

我尝试过那个。但现在我得到了行的多个条目,而且顺序是随机的。 - Harsha M V
@HarshaMV 尝试将这样的声明 holder.placeTitle = (TextView) convertView.findViewById(R.id.place_title);getView 方法的 if 部分移到 else 部分。如果这样不起作用,那么就在 if..else 后面放置。 - Pratik Sharma
没听懂您的意思。您能否请解释一下? - Harsha M V
@HarshaMV,请查看我发布的编辑后的解决方案。我已经展示了哪些地方适合声明持有者控件。 - Pratik Sharma
是的,我错过了getCount方法。刚刚添加了它,现在它可以工作了 :( - Harsha M V

1

尝试使用这段代码来开发您的应用程序,

if (g.getPlaceName().toLowerCase().contains(constraint.toString().toLowerCase())){
    results.add(g);
}

我想要使用特定的.startsWith。 - Harsha M V

1

如果你进行调试,你会发现mPlaces.getSize()等于1,而尝试访问位置1的项时,你会得到一个ArrayOutOfBounds异常。

你的ArrayList可能有问题,很可能没有你想要获取的所有数据。


我应该从哪里开始调试?列表在加载时就已经填充了。只有当我尝试输入和过滤时才会出现问题。 - Harsha M V
尝试在getView的开头设置断点,看看它会带你去哪里。 - thepoosh
2
当我输入一些内容时,它直接跳转到“无结果”。http://pastebin.com/7q4dQC4B 真奇怪:( - Harsha M V
1
我会确保在构造函数中,mPlaces.size() 大于1,然后调试 getView 看看出了什么问题。 - thepoosh
另外,在查看您的pastebin编辑后,我注意到您不再将约束与g.getPlaceName()进行比较,这是原始帖子中的意图,因此如果您遵循相同的数据模型,则应该是item.getPlaceName()。感谢您发布所有这些内容! - whyoz

0
如果有人需要在自定义操作栏中使用 SearchView 的代码,并将其放入您的活动(或在此情况下为ListFragment)中,以下是代码:
    ActionBar actionBar = getActivity().getActionBar();
    actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_SHOW_HOME);
    actionBar.setDisplayShowHomeEnabled(true);
    actionBar.setCustomView(R.layout.your_bar);
    SearchView groupSV = (SearchView)actionBar.getCustomView().findViewById(R.id.groupSV);
    groupSV.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextChange(String newText) {
            Log.d(TAG,"onQueryTextChange");
            ListViewFragment.adapter.getFilter().filter(newText);
            return true;
        }
        @Override
        public boolean onQueryTextSubmit(String query) {
            Log.d(TAG,"onQueryTextSubmit");
            //ListViewFragment.adapter.getFilter().filter(query);
            return true;
        }
    });

在你的ListViewFragment中,你需要将你的适配器声明为静态的,像这样:

public static ArrayAdapter<Your_obj> adapter = null;

public class ListViewFragment extends ListFragment implements OnItemClickListener {
    //...//
}

另外,请确保查看原帖作者从链接中编辑过的代码:PASTEBIN EDITS


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