Adapter Views - nhaarman/Triad GitHub Wiki
Triad makes dealing with AdapterViews
such as ListView
a bliss. Each item in the ListView
is backed by a single Presenter. This simplifies state management a lot, and helps you keep your code cleaner as well.
Let's say we want to show a list of notes in a NotesContainer
. Our NotesPresenter
will fetch the notes from a repository, wrap them in Presenters, and forward them to the Container:
class NotesPresenter extends Presenter<NotesContainer, ActivityComponent> {
/**
* Provides storage for our notes.
*/
@NonNull
private final NotesRepository mNotesRepository;
@Nullable
private List<NotePresenter> mNotePresenters;
NotesPresenter(@NonNull final NotesRepository notesRepository) {
mNotesRepository = notesRepository;
}
@Override
public void onControlGained(@NonNull final NotesContainer container, @NonNull final ActivityComponent activityComponent) {
if (mNotePresenters == null) {
List<Note> notes = mNotesRepository.getNotes();
mNotePresenters = new ArrayList<>(notes.size());
for (Note note : notes) {
mNotePresenters.add(new NotePresenter(note));
}
}
container.setNotes(mNotePresenters);
}
}
Our Container extends ListViewContainer
, and manages the ListAdapter
:
public class NotesView extends ListViewContainer<NotesPresenter, ActivityComponent> implements NotesContainer {
@NonNull
private final NotesAdapter mAdapter;
@Nullable
private List<NotePresenter> mNotes;
public NotesView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle, NotesListPresenter.class);
mAdapter = new NotesAdapter();
}
@Override
public void onFinishInflate() {
super.onFinishInflate();
setAdapter(mAdapter);
}
@Override
public void setNotes(@NonNull final List<NotePresenter> notes) {
mNotes = notes;
mAdapter.notifyDataSetChanged();
}
private class NotesAdapter extends BaseAdapter {
@Override
public int getCount() {
return mNotes == null ? 0 : mNotes.size();
}
@Override
public NotePresenter getItem(final int position) {
return mNotes == null ? null : mNotes.get(position);
}
@Override
public long getItemId(final int position) {
return position;
}
@Override
public View getView(final int position, final View convertView, final ViewGroup parent) {
NoteContainer view = (NoteContainer) convertView;
if (view == null) {
view = (NoteContainer) LayoutInflater.from(getContext()).inflate(R.layout.view_note, parent, false);
}
view.setPresenter(getItem(position));
return (View) view;
}
}
}
The only thing left to do is to fill the NoteContainer
when the NotePresenter
gains control over it:
class NotePresenter extends Presenter<NoteContainer, ActivityComponent> {
@NonNull
private final Note mNote;
NotePresenter(@NonNull final Note note) {
mNote = note;
}
@Override
public void onControlGained(@NonNull final NoteContainer container, @NonNull final ActivityComponent activityComponent) {
container.setTitle(mNote.getTitle());
container.setContents(mNote.getContents());
}
}
Implementing ListViews
this way makes for clean, modular and highly testable code.