IndexOutOfBoundException on filtering SimpleAdapter

此生再无相见时 提交于 2019-12-02 12:56:08

问题


I sub classed SimpleAdapter to add some extra functionality to it, like changing background color, custom views and filtering. The background thing is working out great but the filter isn't. If I use the SimpleFilter provided by the adapter there is no problem at all, so I copied the methods from the source and put them into my adapter. Although I didn't touch anything I'll get a IndexOutOfBoundsException when typing in the search term. Usually on the second or third character.

I copied the whole class but the interesting part is the CustomFilter bindView and getView is working great. After implementing the filter changed it stops working. The exception is caused by data.get(position) in the bindView method on the first line but the problem has to be the filter.

public class ChangingColorAdapter extends SimpleAdapter {

    int resource;
    int[] to;

    List<Map<String, String>> data, mUnfilteredData;
    String[] from;

    Context context;
    Resources res;
    Filter filter;

    /*
     * A custom adapter which changes background colors on the elements
     * and implements custom filtering
     */
    public ChangingColorAdapter(Context context,
            List<Map<String, String>> data, int resource, String[] from, int[] to) {

        super(context, data, resource, from, to);
        this.context = context;
        this.resource = resource;
        this.data = data;
        this.from = from;
        this.to = to;
        this.res = context.getResources();

    }

    @Override
    public Filter getFilter() {
        if(filter != null) return filter;
        else return filter = new CustomFilter();
    }

    /*
     * A custom filter which is copied from the simplefilter in simpleadapter.
     * Changed word check from .startswith to .contains
     */
    private class CustomFilter extends Filter {

        @Override
        protected FilterResults performFiltering(CharSequence prefix) {
            FilterResults results = new FilterResults();

            if (mUnfilteredData == null) {
                mUnfilteredData = new ArrayList<Map<String, String>>(data);
            }

            if (prefix == null || prefix.length() == 0) {
                List<Map<String, String>> list = mUnfilteredData;
                results.values = list;
                results.count = list.size();
            } else {
                String prefixString = prefix.toString().toLowerCase();

                List<Map<String, String>> unfilteredValues = mUnfilteredData;
                int count = unfilteredValues.size();

                ArrayList<Map<String, ?>> newValues = new ArrayList<Map<String, ?>>(count);

                for (int i = 0; i < count; i++) {
                    Map<String, ?> h = unfilteredValues.get(i);
                    if (h != null) {

                        int len = to.length;

                        for (int j=0; j<len; j++) {
                            String str =  (String)h.get(from[j]);

                            String[] words = str.split(" ");
                            int wordCount = words.length;

                            for (int k = 0; k < wordCount; k++) {
                                String word = words[k];

                                if (word.toLowerCase().contains(prefixString)) {
                                    newValues.add(h);
                                    break;
                                }
                            }
                        }
                    }
                }

                results.values = newValues;
                results.count = newValues.size();
            }

            return results;
        }

        @SuppressWarnings("unchecked")
        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            data = (List<Map<String, String>>) results.values;
            if (results.count > 0) {
                 notifyDataSetChanged();
            } else {
                 notifyDataSetInvalidated();
            }
        }
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View v;
        if (convertView == null) {
            LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = inflater.inflate(resource, parent, false);
        } else {
            v = convertView;
        }

        bindView(position, v);

        if(position%2!=0) {
            v.setBackgroundColor(Color.DKGRAY);
        }
        else {
            v.setBackgroundColor(Color.BLACK);
        }

        return v;
    }

    /*
     * Iterate over all elements, check which type the given view is and fill in the data
     */
    private void bindView(int position, View view) {
        final Map<String, String> dataSet = data.get(position);
        if (dataSet == null) {
            return;
        }

        final ViewBinder binder = getViewBinder();
        final String[] from = this.from;
        final int[] to = this.to;
        final int count = to.length;

        for (int i = 0; i < count; i++) {
            final View v = view.findViewById(to[i]);
            if (v != null) {
                final Object data = dataSet.get(from[i]);
                String text = data == null ? "" : data.toString();
                if (text == null) {
                    text = "";
                }

                boolean bound = false;
                if (binder != null) {
                    bound = binder.setViewValue(v, data, text);
                }

                if (!bound) {
                    if (v instanceof Checkable) {
                        if (data instanceof Boolean) {
                            ((Checkable) v).setChecked((Boolean) data);
                        } else if (v instanceof TextView) {
                            setViewText((TextView) v, text);
                        } else {
                            throw new IllegalStateException(v.getClass().getName() +
                                    " should be bound to a Boolean, not a " +
                                    (data == null ? "<unknown type>" : data.getClass()));
                        }
                    } else if (v instanceof TermView) {
                        if(text.length()==10) {
                            int year = Integer.parseInt(text.substring(0,4));
                            if(text.substring(5, 7).equals("04")) {
                                setViewText((TextView) v, res.getString(R.string.summerterm) + " " + year);
                            }
                            else {
                                setViewText((TextView) v, res.getString(R.string.winterterm) + " " + year + "/" + (year+1));
                            }   
                        }
                        else {
                            setViewText((TextView) v, text);
                        }
                    } else if (v instanceof TextView) {
                        setViewText((TextView) v, text);
                    } else if (v instanceof ImageView) {
                        if (data instanceof Integer) {
                            setViewImage((ImageView) v, (Integer) data);                            
                        } else {
                            setViewImage((ImageView) v, text);
                        }
                    } else {
                        throw new IllegalStateException(v.getClass().getName() + " is not a " +
                                " view that can be bounds by this SimpleAdapter");
                    }
                }
            }
        }
    }
}

回答1:


Try this code:

@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
    data.clear();
    data.addAll((List<Map<String, String>>) results.values);
    if (results.count > 0) {
       notifyDataSetChanged();
    } else {
       notifyDataSetInvalidated();
    }
}



回答2:


No need to add filter and bindView methods, only make sure for getView:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View v = super.getView(position, convertView, parent);

    if(position%2!=0) {
        v.setBackgroundColor(Color.DKGRAY);
    }
    else {
        v.setBackgroundColor(Color.BLACK);
    }

    return v;
}


来源:https://stackoverflow.com/questions/10258115/indexoutofboundexception-on-filtering-simpleadapter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!