I have two classes, PersonAdapter and AnimalAdapter.
Both classes are almost identical so I'm trying to reduce as much boiler plate code as possible.
PersonAdapter extends from RecyclerView.Adapter.
AnimalAdapter extends from RecyclerView.Adapter. Both classes implements the Filterable interface.
PersonAdapter defines an inner class PersonFilter extending from Filter.
AnimalAdapter defines an inner class AnimalFilter extending from Filter.
I would like to replace PersonFilter and AnimalFilter with some kind of generic class, but I don't know how since these are the differences between both classes:
PersonFilter
- works with a List<Person>
- uses Person#getName() to make a string comparison
AnimalFilter
- works with a List<Animal>
- uses Animal#getType() to make a string comparison
Please take a quick look at both classes:
PersonAdapter
public class PersonAdapter extends RecyclerView.Adapter<PersonViewHolder> implements Filterable {
private List<Person> persons;
private PersonFilter personFilter;
public PersonAdapter(List<Person> persons) {
this.persons = persons;
}
...
@Override
public Filter getFilter() {
if(personFilter == null)
personFilter = new PersonFilter(this, persons);
return personFilter;
}
public static class PersonFilter extends Filter {
private final PersonAdapter adapter;
private final List<Person> originalList;
private final List<Person> filteredList;
private PersonFilter(PersonAdapter adapter, List<Person> originalList) {
super();
this.adapter = adapter;
this.originalList = new LinkedList<>(originalList);
this.filteredList = new ArrayList<>();
}
@Override
protected FilterResults performFiltering(CharSequence constraint) {
filteredList.clear();
final FilterResults results = new FilterResults();
if (constraint.length() == 0) {
filteredList.addAll(originalList);
} else {
final String filterPattern = constraint.toString().toLowerCase().trim();
for (final Person person : originalList) {
if (person.getName().toLowerCase().contains(filterPattern.toLowerCase())) {
filteredList.add(person);
}
}
}
results.values = filteredList;
results.count = filteredList.size();
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
adapter.persons.clear();
adapter.persons.addAll((ArrayList<Person>) results.values);
adapter.notifyDataSetChanged();
}
}
}
AnimalAdapter
public class AnimalAdapter extends RecyclerView.Adapter<AnimalViewHolder> implements Filterable {
private List<Animal> animals;
private AnimalFilter animalFilter;
public AnimalAdapter(List<Animal> animals) {
this.animals = animals;
}
...
public static class AnimalFilter extends Filter {
private final AnimalAdapter adapter;
private final List<Animal> originalList;
private final List<Animal> filteredList;
private AnimalFilter(AnimalAdapter adapter, List<Animal> originalList) {
super();
this.adapter = adapter;
this.originalList = new LinkedList<>(originalList);
this.filteredList = new ArrayList<>();
}
@Override
protected FilterResults performFiltering(CharSequence constraint) {
filteredList.clear();
final FilterResults results = new FilterResults();
if (constraint.length() == 0) {
filteredList.addAll(originalList);
} else {
final String filterPattern = constraint.toString().toLowerCase().trim();
for (final Animal animal : originalList) {
if (animal.getType().toLowerCase().contains(filterPattern.toLowerCase())) {
filteredList.add(animal);
}
}
}
results.values = filteredList;
results.count = filteredList.size();
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
adapter.animals.clear();
adapter.animals.addAll((ArrayList<Animal>) results.values);
adapter.notifyDataSetChanged();
}
}
}
How should I create a generic subclass of Filter that works both with Animal and Person objects and can be used by PersonAdapter and AnimalAdapter?