notes: A Journey Through MV Wonderland w/ Florina Muntenescu

Posted by


I chose this talk because I wanted a quick comparison of different presentation patterns (mainly MVP and MVVM) as understood and accepted by the Android community.

It’s about MV(C|P|VM) where the M and V stand for Model and View respectively.

The Model is the interface from which data is retrieved and through which data is modified.

The View is the interface that displays the data.


NB: this is from 2016, before Android Architecture Components was released. Any reference to “ViewModel” is not referring to this library, but rather the concept as described in MVVM.

For a brief introduction to the Android Architecture Components, check out the Android Dialogs episode with Lyla Fujiwara, where they discuss ViewModel and LiveData.


How do you apply Model-View-Controller in Android?

(4:00) Implementing MVC on Android often resulted in the Activity taking the role of both the View and the Controller.

(4:46) Rather, keep the Activity as the View, which can tell the Controller (a separate class) about user input.

What is the Controller? It’s the interface responsible for:

  • updating the Model in response to user input
  • notifying the View that it should update (the View then requests updated data from the Model)

View implements IView. View and Controller have a reference to each other. View and Controller each have a reference to the Model

(5:16) To avoid the Controller knowing about Android concepts, like the Activity or Fragment, create an interface for the View (IView) that the Activity implements.

The Controller can keep a reference to IView which can then be swapped out in unit tests.

Transitioning from MVC to Model-View-Presenter

(6:40) The View ends up knowing too much with references to both the Controller and the Model, and leads to large Activity or Fragment classes with a lot of logic.

(7:14) Let’s break the connection between the View and the Model. Let only the Controller interact with the Model:

View and Controller still have a reference to each other, but now only the Controller has a reference the Model

The Controller can get data from the Model, apply any UI logic (e.g. formatting), and then tell the View what it should present.

This is essentially Model-View-Presenter.

Model-View-Presenter

View implements IView and Presenter implements IPresenter. View and Presenter have a reference to each other (via the interfaces) and the Presenter has a reference to the Model

The View and Presenter have a reference to each other. Since each one has its own interface, the interfaces and the Presenter implementation can live in a separate module without Android dependencies.

IView exposes methods that allow the Presenter to update the UI.

(I’m not sure there is much value in having an interface for the Presenter — since the IView interface abstracts away the Activity or Fragment, the Presenter doesn’t need to have Android dependencies to begin with and can be in any module.)

(8:20) The View tells the Presenter when it’s ready to display data by calling IPresenter.onLoad().

https://gist.github.com/ataulm/e2046a17a25eb64583433a7e4ca0cc87

Here, the Presenter can load data from the Model, apply any UI logic, then update the View:

https://gist.github.com/ataulm/b33bbb294850581b6dce25816a1b34ef

The View also notifies the Presenter about user actions. Then the Presenter is responsible for deciding what should happen next — updating the Model or the View.

Transitioning from MVP to MVVM with Observables

(10:00) Looking at this from an event-based point of view, the Presenter produces data and the View consumes data.

Why should the producer (the Presenter) know about the consumer (the View)? The producer shouldn’t care.

Instead, the Presenter should emit data events, and anything that’s interested should be able to subscribe to this event stream.

So we can add another method that exposes a stream of events:

https://gist.github.com/ataulm/d2cc36208614b94eb498e41fe7b34929

The View can subscribe to this:

https://gist.github.com/ataulm/accd8da14f399d72d3c1eb7e5020929d

(11:05) Now, the Presenter doesn’t call IView.setName(String). In fact, the Presenter doesn’t need a reference to the View at all, so we can get rid of the IView interface.

There’s no need to call IPresenter.onLoad() either, because the View will subscribe to the event streams that the Presenter exposes as soon as it’s ready to display data.

View has a reference to the “Presenter” and the “Presenter” has a reference to the Model

We’re left with Model-View-ViewModel.

Model-View-ViewModel

(11:25) MVVM was introduced by Microsoft to simplify event-based implementations of user interfaces.

View has reference to the ViewModel and the ViewModel has a reference the Model

The ViewModel gets the data from the Model, applies any UI logic, and emits UI state events to whatever subscribes to it — the View, the tests, or other classes (e.g. another ViewModel).

(12:17) Rather than exposing multiple event streams, like so:

https://gist.github.com/ataulm/bee09ccd14937620e4bee66399b7dc01

the ViewModel should expose the complete UI state (or a model) for the View:

https://gist.github.com/ataulm/804f5d2b5c47cc1928d4eb8631a60027

Differences between MVP and MVVM

(13:10) The Presenter has a reference to the View, telling it what to display. The View also has a reference to the Presenter so that it can notify the Presenter about any user actions.

In MVVM, the ViewModel does not have a reference to the View; it doesn’t know about it. The View has a reference to the ViewModel, so it can subscribe to event streams of UI models, and also notify the ViewModel about user actions.

Other notes

For me, the biggest takeaway was getting a quick overview of these different presentation patterns and how they relate to each other.

(13:50) The talk also includes an overview on how you might implement MVP/MVVM in Android apps, highlighting that the Activity, Fragment or custom Android Views can all be the View from MV(P|VM).

(15:53) Florina continues by showing us how to decide what goes in the View and what goes in the Presenter/ViewModel.


If it contains UI logic, it needs to go in the Presenter/ViewModel because it needs to be tested.

(16:55) Florina talks about UI which can have parts that are co-dependent, like a form button that is only enabled when all the fields are filled in. She explains how you can approach this with:

  • data persisted in the Model, consumed by multiple Presenters or multiple ViewModels
  • composite Presenters
  • multiple ViewModels, where one consumes the events of another

Multiple custom Android Views in the same layout, each with their own ViewModel. One of the ViewModels has a reference to one of the others, indicating that the UI state of that View is dependent on the other.

(18:13) When should the View tell the Presenter that it’s ready to start loading or when should the View subscribe to events from the ViewModel?

(18:37) How (and where) can we persist state from Presenters and ViewModels on configuration changes?

Conclusion

“Which one should you use? Actually, it doesn’t matter. What all these patterns do is create a common language between you and your team.”

Be consistent, don’t be dogmatic. Ask yourself these questions:

  • Are your Android classes logic free?
  • Can you unit test your classes?
  • Do your classes do one thing and one thing only?

Not yet, but they will be soon. Thanks Florina!