Tan Kahseng
Tan Kahseng

Reputation: 71

Android Listview search filter (list empty after first search)

I am doing a search filter using filterable. I manage to get the search result when I search by keyword but the listview is empty after the first search. I want it to show all the data when the user input is null.

This is the code I edited. Now I cannot get any search result. Any idea which part still wrong?

  public class ProductListAdapter extends BaseAdapter implements Filterable {


    private Context context;
    private int layout;
    private ArrayList<Booth> productList= new ArrayList<>();
    private ArrayList<Booth> tempList = new ArrayList<>();
    private ValueFilter mFilter = new ValueFilter();


    public ProductListAdapter(Context context, int layout, ArrayList<Booth> productList) {
        this.context = context;
        this.layout = layout;
        this.productList = productList;
        this.tempList = productList;


    }

    @Override
    public int getCount() {

        return tempList.size();
    }

    public void addItems(ArrayList<Booth> items) {
        productList.addAll(items);
        tempList.addAll(items);
        notifyDataSetChanged();
    }

    @Override
    public Object getItem(int position) {

        return tempList.get(position);
    }

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

    @Override
    public View getView(
            int position, View view, ViewGroup viewGroup) {
        Typeface face_02 = Typeface.createFromAsset(context.getAssets(), "customfont/grb.otf");
        ViewHolder holder = new ViewHolder();

        if (view == null) {
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(layout, null);
            holder.Boothname = (TextView) view.findViewById(R.id.Boothname);
            holder.Rating = (TextView) view.findViewById(R.id.Rating);

            view.setTag(holder);
        } else {
            holder = (ViewHolder) view.getTag();
        }
        Booth product = productList.get(position);


        holder.Boothname.setText(product.getBoothName());
        holder.Rating.setText(product.getRating());
        holder.Rating.setTypeface(face_02);
        holder.Boothname.setTypeface(face_02);

        return view;
    }

    @Override
    public Filter getFilter() {
        return mFilter;
    }

    private class ValueFilter extends Filter {

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

            if (constraint != null && constraint.length() > 0) {
                ArrayList<Booth> filterList = new ArrayList<Booth>();
                constraint = constraint.toString().toLowerCase();

                for (int i = 0; i < productList.size(); i++) {
                    if ((productList.get(i).getBoothName().toLowerCase())
                            .contains(constraint.toString().toLowerCase())) {

                        Booth boothdata = new Booth(productList.get(i)
                                .getBoothName(), productList.get(i)
                                .getRating());

                        filterList.add(boothdata);
                    }
                }
                results.count = filterList.size();
                results.values = filterList;


            } else {
                results.count = productList.size();
                results.values = productList;
            }
            return results;

        }

        @Override
        protected void publishResults(CharSequence constraint,
                                      FilterResults results) {
            tempList = (ArrayList<Booth>) results.values;
            notifyDataSetChanged();
        }
    }
        class ViewHolder {
            TextView Boothname, Rating;

        }
}

Upvotes: 0

Views: 2421

Answers (2)

Kingfisher Phuoc
Kingfisher Phuoc

Reputation: 8200

yes, you got this error. Why? Because after searchings, from times to times, your productList loses its product. So, how to resolve it? You should make filter data for filtering only and you will search in the filter data instead of your productList as below:

filterList = new List<Product>()// do clone here when you set new data to your list.
// then in the performFiltering(), use filterList instead.
for (int i = 0; i < filterList.size(); i++) {
                if ((filterList.get(i).getBoothName().toLowerCase())
                        .startsWith(constraint.toString().toLowerCase())) {

                    Booth boothdata = new Booth(filterList.get(i)
                            .getBoothName(), filterList.get(i)
                            .getRating());

                    filterList.add(boothdata);
                }
            }

This is what you should do.

    @Override
    protected void publishResults(CharSequence constraint,
                                  FilterResults results) {
        productList = (ArrayList<Booth>) results.values; // if you use templist here, there's no change in getView
        notifyDataSetChanged();
    }

Upvotes: 1

Patel Dhara
Patel Dhara

Reputation: 886

This is happened because you are updating your original list when user search anything.You have to use tempList which is hold temporary data and used to show search result,it is also used to shows list initially.And ProductList contains original list and it is used to compare with the search string.

Initialize variable

private List<Booth> productList=new ArrayList<>(); //you have already done this,this contains original list
private List<Booth> tempList=new ArrayList<>(); //add this one is to show search result

Method for the add data should be like this:

public void addItems(List<Booth> items) {
        productList.addAll(items);
        tempList.addAll(items);
        notifyDataSetChanged();
}

Method for the remove data should be like this:

  public void removeItems(){
        productList.clear();
        tempList.clear();
    }

getItem and getCount method should be like this:

  @Override
    public int getCount() {
        return tempList.size();
    }
    @Override
    public Booth getItem(int position) {
        return tempList.get(position);
}

ValueFilter should be like this:

        private class ValueFilter extends Filter {

            @Override
            protected FilterResults performFiltering(CharSequence constraint) {

            FilterResults results = new FilterResults();

            if (constraint != null && constraint.length() > 0) {
                //filter list as a local variable
                ArrayList<Booth> filterList = new ArrayList<Booth>();
                constraint = constraint.toString().toLowerCase();

                for (int i = 0; i < productList.size(); i++) {
                      if ((productList.get(i).getBoothName().toLowerCase())
                            .startsWith(constraint.toString().toLowerCase())) {

                        Booth boothdata = new Booth(productList.get(i)
                                .getBoothName(), productList .get(i)
                                .getRating());

                        filterList.add(boothdata);
                    }
                }
                results.count = filterList.size();
                results.values = filterList;
                Log.e("VALUES", results.values.toString());
            } else {

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

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

Upvotes: 1

Related Questions