I have implemented Filterable
in my RecyclerView.Adapter<>
to search for specific locations by either their name or district. I log the result in every iteration in the performFiltering()
method in the Filter
like so where filteredLocationList
is a class variable:
private class LocationsAdapter extends RecyclerView.Adapter<LocationsAdapter.MyViewHolder> implements Filterable {
private List<Location> locationList;
private List<Location> filteredLocationList;
LocationsAdapter(List<Location> locationList) {
this.locationList = locationList;
this.filteredLocationList = locationList;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.view_location_row, parent, false);
return new MyViewHolder(itemView);
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
Location location = locationList.get(position);
holder.name.setText(location.locName);
holder.district.setText(location.locDistrict);
}
@Override
public int getItemCount() {
return filteredLocationList.size();
}
@Override
public Filter getFilter() {
return new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
String searchTerm = constraint.toString().toLowerCase();
Log.w(TAG, "search " + searchTerm);
if (searchTerm.isEmpty()) {
filteredLocationList = locationList;
} else {
List<Location> filteredList = new ArrayList<>();
for (Location location : locationList) {
if (location.locName.toLowerCase().contains(searchTerm)) {
Log.i("location search", location.locName);
filteredList.add(location);
}
}
filteredLocationList = filteredList;
}
FilterResults searchResults = new FilterResults();
searchResults.values = filteredLocationList;
return searchResults;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
filteredLocationList = (ArrayList<Location>) results.values;
notifyDataSetChanged();
}
};
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView name, district;
MyViewHolder(View view) {
super(view);
name = view.findViewById(R.id.name);
district = view.findViewById(R.id.district);
}
}
}
The Log statements show the Locations are being found but the List is not updating accordingly. What could be the cause of this.
After referring to this tutorial, I made some changes to the getFilter()
and publishResults()
methods which seemed to have done the trick. The search results' values and count were assigned after searching. In the publishResults the adapter was used
getFilter()
:
searchResults.values = filteredLocationList;
searchResults.count = filteredLocationList.size();
publishResults()
:
adapter.filteredLocationList = (ArrayList<Location>) results.values;
adapter.notifyDataSetChanged();