The clear() in custom listview adapter also updates the list data

六眼飞鱼酱① 提交于 2020-01-14 06:35:30

问题


I am working on a listview filter, that means, there is a editbox, if I type in some keywords , the listview data will change accordingly. To begin with, there is a dataset.

private ArrayList<PostItem> postList;

Assuming the list is already fill with data, here is the adapter with filtering:

private class PostAdapter extends ArrayAdapter<PostItem> implements
        Filterable {

    public PostAdapter(Context context, int resource, List<PostItem> items) {
        super(context, resource, items);
    }

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

        View v = convertView;

        if (v == null) {
            LayoutInflater vi;
            vi = LayoutInflater.from(getContext());
            v = vi.inflate(R.layout.post_item, parent, false);
        }

        PostItem post = getItem(position);

        if (post != null) {
            TextView title = (TextView) v.findViewById(R.id.postTitle);
            TextView date = (TextView) v.findViewById(R.id.postDate);

            v.setTag(post.id);
            title.setText(Html.fromHtml(post.title));
            date.setText(post.name + " "
                    + getResources().getString(R.string.post_on) + " "
                    + post.date);
        }

        return v;

    }

    @Override
    public Filter getFilter() {

        Filter filter = new Filter() {

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

                ArrayList<PostItem> filteredList = (ArrayList<PostItem>)results.values;

                clear();

                for (PostItem item :filteredList) {
                    add(item);
                }
            }

            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                FilterResults results = new FilterResults();
                ArrayList<PostItem> filteredArray = new ArrayList<PostItem>();

                constraint = constraint.toString().toLowerCase();

                for (PostItem item : postList) {
                    if (item.title.toLowerCase().contains(constraint)) {
                        filteredArray.add(item);
                    }
                }

                results.count = filteredArray.size();
                results.values = filteredArray;
                return results;
            }
        };

        return filter;
    }

}

The problem is , clear() function will also remove all the item contains in postList and insert all the latest filtered result. How to fix it? I tried to have a copied variable e.g. copyPostList = postList but still the same. Thanks for helping

Update: More explanation:

  1. First, The postList has item "abc";

  2. Then, Type in "ab", the list show "abc", which is correct

  3. After that, Type in "xyz", the list show nothing, which is correct

  4. Finally, Type in "abc", the list show nothing, which is incorrect


回答1:


public class AutoCompleteAdapter extends ArrayAdapter<String> implements Filterable {

    private ArrayList<String> fullList;
    private ArrayList<String> mOriginalValues;
    private ArrayFilter mFilter;

    public AutoCompleteAdapter(Context context, int resource, List<String> objects) {

        super(context, resource, objects);
        fullList = (ArrayList<String>) objects;
        mOriginalValues = new ArrayList<String>(fullList);

    }

    @Override
    public void add(String object) {
        super.add(object);
        fullList.add(object);
        mOriginalValues.add(object);
    }

    @Override
    public void clear() {
        super.clear();
        fullList.clear();
        mOriginalValues.clear();
    }

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

    @Override
    public String getItem(int position) {
        return fullList.get(position);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        TextView view = (TextView) super.getView(position, convertView, parent);
        view.setEllipsize(TextUtils.TruncateAt.START);
        return view;
    }

    @Override
    public Filter getFilter() {
        if (mFilter == null) {
            mFilter = new ArrayFilter();
        }
        return mFilter;
    }


    private class ArrayFilter extends Filter {

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

            if (mOriginalValues == null) {
                mOriginalValues = new ArrayList<String>(fullList);
            }
            ArrayList<String> list = new ArrayList<String>(mOriginalValues);
            results.values = list;
            results.count = list.size();


            return results;
        }

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

            if (results.values != null) {
                fullList = (ArrayList<String>) results.values;
            } else {
                fullList = new ArrayList<String>();
            }
            if (results.count > 0) {
                notifyDataSetChanged();
            } else {
                notifyDataSetInvalidated();
            }
        }
    }
}

Check it out. this adapter works great. Good luck.




回答2:


Final code , add the filtering and getView for my case

    private class PostAdapter extends ArrayAdapter<PostItem> implements Filterable {

    private ArrayList<PostItem> fullList;
    private ArrayList<PostItem> mOriginalValues;        
    private ArrayFilter mFilter;

    public PostAdapter(Context context, int resource, List<PostItem> objects) {
        super(context, resource, objects);
        fullList = (ArrayList<PostItem>) objects;
        mOriginalValues = new ArrayList<PostItem>(fullList);

    }

    @Override
    public void add(PostItem object) {
        super.add(object);
        fullList.add(object);
        mOriginalValues.add(object);
    }

    @Override
    public void clear() {
        super.clear();
        fullList.clear();
        mOriginalValues.clear();
    }

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

    @Override
    public PostItem getItem(int position) {
        return fullList.get(position);
    }

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

        View v = convertView;

        if (v == null) {
            LayoutInflater vi;
            vi = LayoutInflater.from(getContext());
            v = vi.inflate(R.layout.post_item, parent, false);
        }

        PostItem post = getItem(position);

        if (post != null) {
            TextView title = (TextView) v.findViewById(R.id.postTitle);
            TextView date = (TextView) v.findViewById(R.id.postDate);

            v.setTag(post.id);
            title.setText(Html.fromHtml(post.title));
            date.setText(post.name + " "
                    + getResources().getString(R.string.post_on) + " "
                    + post.date);
        }

        return v;
    }

    @Override
    public Filter getFilter() {
        if (mFilter == null) {
            mFilter = new ArrayFilter();
        }
        return mFilter;
    }


    private class ArrayFilter extends Filter {

        @Override
        protected FilterResults performFiltering(CharSequence prefix) {
            FilterResults results = new FilterResults();
            ArrayList<PostItem> list =  new ArrayList<PostItem>();

            if (mOriginalValues == null) {
                mOriginalValues = new ArrayList<PostItem>(fullList);
            }

            for (PostItem item : mOriginalValues) {
                if (item.title.toLowerCase().contains(prefix.toString().toLowerCase())) {
                    list.add(item);
                }
            }

            results.values = list;
            results.count = list.size();
            return results;
        }

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

            if (results.values != null) {
                fullList = (ArrayList<PostItem>) results.values;
            } else {
                fullList = new ArrayList<PostItem>();
            }
            if (results.count > 0) {
                notifyDataSetChanged();
            } else {
                notifyDataSetInvalidated();
            }
        }
    }
}

Thanks for helping



来源:https://stackoverflow.com/questions/24775171/the-clear-in-custom-listview-adapter-also-updates-the-list-data

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