Simplifying Android Architectures for Developers — MVC, MVP, MVVM, Clean, MVI, VIPER — part 5: MVI
MVI
Theory
This Architecture is based again on 3 layers: Model, View, Intent
Model (Exactly like in MVC, MVP, MVVM)
The model contains Databases, business rules, and access to external resources.
Intent
First of all, do not confound this concept with the native class Intent that belongs to the Android library, it is not the same.
I will start with the new layer. Basically, this is where our connector communicates with the view layer based on events. We can understand that layer as an intent to trigger something somewhere.
Inside that layer, this intent has been split into 3 groups:
Event
Trigger from UI. It could be an interaction or some event from the Android/Fragment lifecycle.
Effect
Trigger for UI to do some update like a Toast, Snackbar, or another type of update that tends not to be persistent in the UI, just to be shown and dismissed.
State
Here will be the current state of our page. It could be something like emptyState, errorState, dataState, loadingState, or another state that would make sense in the context of your application.
Note: We could change from one state to another state of the same type. This could happen, for sample, If you have a client loaded on your page, but for some reason, this client is replaced by another client.
View
This layer is responsible to update UI and receiving UI triggers like clicks, or some life cycle event, and requesting information from the connector layer.
I did not give many details about how this connector that we called Intent will be connected with the View layer.
Should we send an instance from view to that connector like on MVP?
Should our connector expose a kind of Observable or Live data like on MVVM?
The answer is yes to both questions. So, you can follow MVI + MVVM or MVI + MVP. Theoretically, we could force a kind of MVI + MVC, but I guess, as MVC was implemented for Android, It would not make sense, because basically, our activity would send triggers and receive to itself.
Practice
As I did in the Clean Architecture explanation, I will start with the common implementation, and after done I will explain how it is implemented by each architecture
Intent
Event
Effect
State
MVP
MVP + Clean
MVVM
As you saw, I had to add one more library here. The PublishSubject is a class provided by RxJava.
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
That was my choice, but you can do similar stuff with other tools that won’t be explained here.
But first, let me explain why LiveData do is not a good option here. Basically, if you start observing a LiveData when it has already some data, your observer will be triggered immediately.
So let’s suppose you used LiveData to send a simple toast for your UI. After screen rotation, your ViewModel will keep there. So your view will pass through onCreate again, and after you observe it, you will repeat the last event, then your toast will appear again. It won’t happen if you use a PublishSubject. This class does not persist states, it just notifies the observer that was subscribed before the trigger.
MVVM + Clean
You can check this project on GitHub. Remember to select the architecture that you wish to study on the build variants:
Simplifying Android Architectures for Developers — part 1: MVC
Simplifying Android Architectures for Developers — part 2: MVP
Simplifying Android Architectures for Developers — part 3: MVVM
Simplifying Android Architectures for Developers — part 4: Clean
Simplifying Android Architectures for Developers — part 5: MVI
Simplifying Android Architectures for Developers — part 6: VIPER