Java – The RecyclerView search filter does not work

The RecyclerView search filter does not work… here is a solution to the problem.

The RecyclerView search filter does not work

I want to filter some ArrayList data by searching

In the onCreate of my activity:

        arrayList = getListItemData();
        filteredArrayList = new ArrayList<>();
        filteredArrayList.addAll(arrayList);

adapter = new NameAdapter(filteredArrayList);
        itemList.setAdapter(adapter);

searchBox.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

}

@Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

adapter.getFilter().filter(s.toString());

}

@Override
            public void afterTextChanged(Editable s) {

}
        });

My filterable adapter:

public class NameAdapter extends RecyclerView.Adapter<NameAdapter.ViewHolder> implements Filterable {
        private ArrayList<Name> arrayList;
        private CustomFilter filter;

public NameAdapter(ArrayList<Branch> items) {
            arrayList = items;
            filter = new CustomFilter(NameAdapter.this);
        }

@Override
        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_name, parent, false);
            return new ViewHolder(view);
        }

@Override
        public void onBindViewHolder(final ViewHolder holder, int position) {
            holder.data = arrayList.get(position);

}

@Override
        public int getItemCount() {
            return branchArrayList.size();
        }

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

public class ViewHolder extends RecyclerView.ViewHolder {
            public final View view;
            public final TextView branch;
            public Name data;

public ViewHolder(View view) {
                super(view);
                this.view = view;
                branch = view.findViewById(R.id.textView_name);

}

}

public class CustomFilter extends Filter {
            private NameAdapter adapter;

private CustomFilter(NameAdapter adapter) {
                super();
                this.adapter = adapter;
            }

@Override
            protected FilterResults performFiltering(CharSequence constraint) {
                filteredArrayList.clear();
                final FilterResults results = new FilterResults();
                if (constraint.length() == 0) {
                    filteredArrayList.addAll(arrayList);
                } else {
                    final String filterPattern = constraint.toString().toLowerCase().trim();
                    for (final Name name : arrayList) {
                        if (name.getName().toLowerCase().startsWith(filterPattern)) {
                            filteredBranchArrayList.add(name);
                        }
                    }
                }
                results.values = filteredArrayList;
                results.count = filteredArrayList.size();
                return results;
            }

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

this.adapter.notifyDataSetChanged();
            }
        }
    }

The filter doesn’t work for some reason, it clears recyclerview when I type something

Solution

1st Copy the branchArrayList in the constructor. Like this :-

 private ArrayList<Branch> branchCopy = new ArrayList<>;
 public BranchAdapter(ArrayList<Branch> items) {
        branchArrayList = items;
        branchCopy.addAll(items);
        filter = new CustomFilter(BranchAdapter.this);
    }

Your performingFilter

  @Override
  protected FilterResults performFiltering(CharSequence constraint) {
        ArrayList<Branch> branchFilter = new ArrayList<>;
        final FilterResults results = new FilterResults();
            if (constraint.length() == 0) {
                branchFilter.addAll(branchArrayList);
            } else {
                final String filterPattern = constraint.toString().toLowerCase().trim();
                for (final Branch branch : branchCopy) {
                    if (branch.getBranchName().toLowerCase().startsWith(filterPattern)) {
                        branchFilter.add(branch);
                    }
                }
            }
            results.values = branchFilter ;
            results.count = branchFilter.size();
            return results;
        }

Your publishResults

  @Override
  protected void publishResults(CharSequence constraint, FilterResults results) {
      branchArrayList = (ArrayList<Branch>) results.values;  you have done nothing with the filter results 
      notifyDataSetChanged();
  }

Before notifying the mainList change !!

 branchArrayList = (ArrayList<Branch>) results.values;

Add this line to publishResults

You have done NOTHING with the filter results

Related Problems and Solutions