At upday, we’ve been successfully using the Model-View-ViewModel pattern together with RxJava for more than a year and half. After sharing with the community a very high level overview of what this pattern entails, we decided that it’s time to go deeper in the implementation details.
I will present our way of handling Android classes and other 3rd party dependencies, and how we make sure that our code is as unit-testable as possible. I’ll speak about our decision process on how to split classes, may they be Views, ViewModels or DataModels, and the benefits and drawbacks of these separations.
Any non-”Hello World” app will most likely have two things: multiple Activities/Fragments, of which at least one will contain a ListView/RecyclerView. I will show how we decided to implement the navigation between Views and how we test it. Then I’ll show how we handle lists: how is the data added to the list, and how and who listens and reacts to list items taps.
49. Lifecycle of the ViewModel depends on the lifecycle of the View
Only the View has a reference to the corresponding ViewModel
View is declared in the XML
Only other native android classes know about the View
57. class TopNewsStreamView extends Fragment{
}
void bind(){
subscription.add(
viewModel.getTopNewsPages()
.subscribe(pages -> setupPages(pages))
}
void setupPages(TopNewsPages pages){
// based on pages.displayables()
// update RecyclerView.Adapter
// using DiffUtil.calculateDiff
}
58. void bind(){
subscription.add(
viewModel.getTopNewsPages()
.subscribe(pages -> setupPages(pages))
}
void setupPages(TopNewsPages pages){
// based on pages.displayables()
// update RecyclerView.Adapter
// using DiffUtil.calculateDiff
}
// based on pages.position()
// update position
class TopNewsStreamView extends Fragment{
}
65. ViewModel creates and emits the Model of the View
View subscribes to the emissions of the Model
View updates the RecyclerView.Adapter
In Adapter.onCreateItemView the RecylerView’s item and
the corresponding ViewModel are created.
78. class TopNewsViewHolder implements
RecyclerView.ViewHolder {
}
TextView title;
…
void bindItem(Displayable displayable){
title.setText(displayable.article().getTitle())
}
view.setOnClickListener(
v -> displayable.onClickAction().call())
79. Define an Action in the View’s Model
Bind the Model to the View via the RecyclerView.ViewHolder
Trigger the Action
Action is handled by the ViewModel