As a simplified example, consider a ListView
that can contain both sub-categories and book titles. If a book title is clicked, a new activity should start that shows the cover image. If a sub-category is clicked, a new list of books and categories is displayed.
A Row
interface is defined as follows.
interface Row {
void onClick();
void draw(View v);
}
I would like to know how to prevent a dependency from the ListView
's ArrayAdapter
as well as from the implementer of onItemClickListener
on the Row
implementers (e.g.,Book
and Category
).
One of the forces driving this requirement is the "don't repeat yourself" (DRY) principle: the ArrayAdapter
implementation does not need to change when new row types are introduced.
Forgive my chicken-scratched "UML" below, but here's how I do it.
class ListAdapter extends ArrayAdapter<Row<?>> {
...
public View getView(int position, View convertView, ViewGroup parent) {
View view = listViewRowViewRecycler.getView(convertView);
rowProvider.get().getRow(position).draw(view);
return view;
}
}
The implementer of OnItemClickListener
has a method like this:
void onItemClick(AdapterView<?> adapterView, View view, int rowIndex, long rowId)
{
rowProvider.onItemClick(rowIndex);
}
Then RowProvider
has a method like this:
void onItemClick(int rowIndex) {
rowList.get(rowIndex).onClick();
}
Then the Row
interface has a method with signature void onClick()
and there are Category
and Book
implementations of Row
that provide the necessary behavior.