Simple MVI Application with view models, live data, presenter and data binding. Same functionality coded in java/kotlin to explain how MVI pattern can be implemented in different scenarios:
MVI pattern means Model-View-Intent. This is not very popular among android development and is very closly related to MVP(Model view presenter) and MVVM(Model view view-Model) patterns of android.
Model : Acts as the model for data. It can be network models, local database models or any other type of data classes.
View : Deals with the view to the user which can be the UI. As usual the view layer is always dumb and is unware of bussiness logics of the application.
Intent : Now this is something new. Intents basically represents the states of an acitivity, frament, dialog etc. Intents can be called as "STATE MODELS".
Note: Intent in MVI is not the same as android's traditional Intent(android.content.Intent). MVI intents are just like data clasess but the only different between them is that MVI intents represents the state of UI.
Let us understand this one with an example. Suppose we have a login screen.
- Not - started -> When login screen is just launced and user saw it for the first time.
- Login - progressing -> When user press the login button to initiate the login process. User can see progress bar that time and login button or other input fields are disabled.
- Login - error -> When the login process is finished. It failed due to some reason and user can see error message on the screen.
- Login - successful -> When the login process is finished. It was successful and user received the user token.
Let's see some code now for these states:
LoginStateInten class maintains all the sufficient data to represent the state of login screen. We handle the state data in renverView() function: Since renderView() function is the only place where we recieve the UI-state model to update the login UI so this is also called single source of truth.
Simple flow of application in MVI is flow of intents between bussiness layer and UI update. This flow is unidirectional and single souce of truth.
This repository explains the following:
- MVI integration with presenter(from MVP) concept- JAVA.
- MVI integration with presenter(from MVP) concept - KOTLIN.
- MVI integration with Databinding and view-Model(from MVVM) concept- JAVA.
- MVI integration with Databinding and view-Model(from MVVM) concept- KOTLIN.
- MVI integration with Livedata and view-Model(from MVVM) concept- JAVA.
- MVI integration with Livedata and view-Model(from MVVM) concept- KOTLIN.
- No state problem anymore, because there is only one state for our view, which is a single source of truth. We can know the state of view at any moment just by knowing the value of it's UI- Intent.
- Unidirectional data flow, which makes the logic of our view more predictable and easier to understand.
- Unidirectional data flow ensures that our app is easy to debug. Every time we pass our data from one component to another, we can log the current value of the outflow. Thus, when we get a bug report, we can see the state our app was in when the error was made, and we can even see the user’s intent under which this state was created.
- Easy scalability if we want add more UI-states to an activity. We just have to add code of new UI-states in sending and receiving logic. This makes testing cycle small and easy.
- Better decoupled logic than MVC, MVP, MVVM.
- Easier to understand code as we know there is a single point where we update UI and single point where we handle user inputs in bussiness layer.
- A lot of boilerplate. Each small UI change has to start with a user’s intent and then must pass the whole circle. Even with the easiest implementation, you have to create at least an intent and a state object for every action made in our app.
- Object creation, which is expensive. If too many objects are created, your heap memory can easily reach full capacity and then your garbage collector will be too busy. You should strike a balance between the structure and size of your app.