MVI Models – Android Tutorial for Beginners

Tram Ho

Introduce

Android architectural patterns are evolving day by day. As we develop applications, we begin to have new challenges and problems. New patterns will be discovered as we continue to tackle similar challenges. As Android Devs, we already know the MVC, MVP and MVVM patterns are the most commonly used patterns. They all use the command programming method. With this approach, although most of our problems will be solved, we still face a number of issues related to thread safety, maintaining the state of the application. With this section, let’s take a look at what the MVI architecture model is, how it addresses these challenges and how to get started with MVI.

In this blog we will learn about

What is MVI architecture? How does MVI work? Advantages and disadvantages of MVI Create a project with an MVI architecture

Source: https://blog.mindorks.com/mvi-architecture-android-tutorial-for-beginners-step-by-step-guide

What is MVI architecture?

MVI stands for Model-View-Intent . This model was recently introduced in Android. It works on the principles of one-way flow and cylindrical flow inspired by the Cycle.js framework.

Let’s see what the role each component of MVI is.

  • Model : Unlike other patterns, In MVI Model represents the state of the user interface. for example, the UI can have different states like Loading data , Loaded , Changing UI with User Actions, Error, Current screen location status of the user . Each state is stored similarly to the object in the model.
  • View : View in MVI is our Interface that can be implemented in Activities and fragments. It means there is a container that can accept different model states and display it as the user interface. They use observable intents (Note: This does not represent traditional Android Intents) in response to user actions.
  • Intent : Although this is not an Intent as defined by Android. The results of the user actions are passed as input values ​​to Intents. In return, we could say that we would send the models as input to the Intent that could load it through the View.

How does MVI work?

The user performing an action would be Intent → Intent which is the input state to the model → Model stores the state and sends the requested state to View → View Loads the state from Model → Visible to the user. If we observe, the data will always flow from the user and end up with the user through the intent. It can’t be the other way around, so it’s called One-dimensional architecture. If the user performs one more action then the same cycle is repeated, so it is Cyclic.

Advantages and disadvantages of MVI

Advantages of MVI

  • Staying state is no longer a challenge with this architecture, as it is primarily focused on states.
  • Since it is one-way, it is easy to monitor and predict Data Flow.
  • It ensures thread safety because state objects are immutable.
  • Easy to debug, As we know the state of the object when an error occurs.
  • It is more fragmented as each of the actors fulfills their own responsibility.
  • Application testing will also be easier because we can map the business logic for each state.

Disadvantages of MVI

  • It leads to a lot of boilerplate code because we have to maintain state for each user action.
  • As we know, it must create lots of objects for all states. This makes managing application memory too expensive.
  • Handling the alert state can get stuck while we are dealing with configuration changes. For example, if internet is not available, we will show the snack bar, When changing the profile, it re-shows the quick bar as the status of the purpose. In terms of usability, this must be handled. With this background, let’s create a small application with MVI

Create a project with MVI architecture

Let’s start by setting up the Android project.

Project Structure

As for the project, We will follow each step of the project using MVI. Our package in the project will look like below.

Establishment of data layers

Now, in this section, we will set up the data layer. In the data package, we will have api, model and repository packages. We will create these packages and let’s focus on adding classes to the packages one by one.

Let’s add API support classes.

We need a model to which the response will be converted. Create the User.kt data class as shown below.

Create ApiHelper.kt interface

Note: We have used suspend keyword to support Coroutines so that we can call it from a Coroutine or another suspend function.

Create an ApiService.kt class where we will specify HTTP methods to communicate with the API.

Now let’s add the retrofit builder to generate endpoint URLs and use REST services.

We need to implement the interface to get List <Users>, create ApiHelperImpl.kt

We are now ready to communicate with the rest of the Services in our data layer.

We will need a repository to request data. In our case, we are calling the getUsers method from operation through the ViewModel to get the list of users. Create MainRepository.kt

So our data layer is ready. Coming to UI, we need an adapter for recyclerview, Purpose to store user action, our main activity in view, MainViewModel in viewModel, View state where we specified defines the different states we need to load data into the view.

Create the MainAdapter in the adapter package

Create MainIntent.kt in intent package

Now add MainState.kt under package viewstate. This is the most important part of MVI. In this class, we are defining the Waiting, loading, user, error states. Each state can be loaded into the view according to the user’s intentions.

Create ViewModel class – MainViewModel

Here in ViewModel, we observing userIntent to perform action on it.

And based on the response from the data class, we change the state inside the fetchUser method. And that state is being observed in MainActivity.

We set up ViewModelFactory according to the util package.

We are instantiating the viewModel in this class and we will return the version of ViewModel.

Now let’s set up the XML layout.

update activity_main.xml:

Add item_layout.xml:

And string is in strings.xml.

With class MainAcitvity.kt. We will add under view package. This is the user-oriented activity and takes input from the user, this MVI based on this checks the states mentioned in the viewModel and loads the specific state in the view.

Let’s see how MainActivity handles data requests, handles status

Here, we are submitting the data fetch intent when the (User Actions) button is clicked.

Also, we observing the ViewModel State for changes to state. And, using the “when” condition, we are comparing the response intent state and loading the corresponding states.

Finally, add Internet Access to your project. Add the following to AndroidManifest.xml:

Conclude

Since we did some of the simplification steps in this project for the Beginners level, so we can improve this project to Advanced level, some things we can improve like after:

Dependency Inject Framework – Dagger is deployed in the project. Create ApiService Singleton and reuse same version for all features. Create base classes like BaseActivity. Handling all API errors in one place in a better way. Create Interfaces for classes whenever needed. Take advantage of Android’s KTX – Kotlin extensions. Write Unit-Test and the like.

I hope you have a better understanding of MVI. and use the right models for your project

Have fun!

Share the news now

Source : Viblo