

MVVM with Kotlin — Android Architecture Components, Dagger 2, Retrofit and RxAndroid
When I wrote my last article MVP Architecture with Kotlin — Dagger 2, Retrofit, RxAndroid and DataBinding I didn’t expect that much: it reached more than 3K reads, and more than 1K applauses.
Within that time, I hardly tried to switch from MVP to MVVM, meaning I tried to find an MVVM architecture which would be definitively more useful that the MVP one I used, and after improving time after time this architecture, I finally found something I’m happy with.
And because your feedbacks on first article gave me motivation, I decided to share it here.
This post was written with the aim to show how I made everything work together in my own MVVM architecture, but not to explain what MVVM or those libraries are or how they work.
The full source code of this project as it is at the end of this article can be found on MVVMPosts repository on GitHub:
Some parts of this article will just be exactly the same as in my MVP articles, as some things (Model, retrieve data from API, …) are exactly the same.
The project we will develop
Our project will be based on JSONPlaceholder API in order to display a list of blog posts.
The application will try to get posts from the local database. If there is no post in it, it will retrieve them from JSONPlaceholder API, then will save them in database.
Initialization of the project
Let us start a new Android Studio project named MVVMPosts, with net.gahfy.mvvposts as package name. We will also include Kotlin support.


Then, we will define 15 as minimum SDK, and add no Activity.
Bases


The only thing we will implement here is a BaseViewModel in order to perform dependency injection in it. Let us first add a base package on root package of the application.
Lifecycle library
We want the BaseViewModel to extend the ViewModel class of Android Architecture Components. So we will add a dependency to the lifecycle extension library (which includes both ViewModel and LiveData libraries) in our project.
In the project’s build.gradle file, add a line to define the version of the lifecycle extension library:
Then in the module’s build.gradle file, add the dependency to the lifecycle extension library:
After syncing the project with gradle files, you will be able to add the BaseViewModel class.
BaseViewModel
Add a kotlin class named BaseViewModel in the base package we just created. As we will use it for dependency injection only, we will leave it empty for now:
Model


Now that we have created the base ViewModel, let us focus on the model. All is just about defining Post object as it is in the JSONPlaceholder API.
We will simply add a model package to the root package of the application in order to host the Post class:
Retrofit


Now that model is done, we will have to retrieve a list of Post from the JSONPlaceholder API. Because we will use Retrofit to do so, we will add a dependency to that library. First, edit the project’s build.gradle file in order to add the version number of the Retrofit library:
We will also add Retrofit’s adapters and converters as we will use RxJava to subscribe to the API calls and Moshi to parse the JSON files. Just add the following lines to the module’s build.gradle file:
Let us create now a package named network in which we will place the interface PostApi in charge of retrieving posts:
We will take the opportunity to create a Kotlin file named Constants.kt in a package named utils to define some constants. We will start with the base url of the JSONPlaceholder API:
That’s it. We will instantiate Retrofit in the next part about Dagger 2.
Dagger 2


Now, let us take advantage of dependency injection to let Retrofit services be injected in the ViewModel. First, let us add the version number of the Dagger library in the project’s build.gradle file:
We will start by adding Dagger 2 libary dependency in the build.gradle file of the module. As Dagger 2 includes an annotation processor, we will also have to apply kotlin-apt plugin to the module:
Injecting Retrofit
We will have to create a module to inject the Retrofit instance in the ViewModel. We will name this module NetworkModule and will place it in a package namedmodule which is placed in a package named injection which has to be added to the root package of your application.
We will also make the module and provider methods Singleton as we do not want to instantiates those each time we use it:
Now that the modules are developed we can go further to the development of the application itself.
Post MVVM


We will add a package ui to the root package of the application, and will add a post package to the ui one in order to add Views and ViewModels related to posts in it.
ViewModel component and injection
Let us create a PostListViewModel class which will be our ViewModel. For now, we will only get results from API then display it in the view.
First thing we will need so is an instance of PostApi class in order to get the result from API. This instance will be injected by Dagger:
Then, we will create a component package in injection package and create a ViewModelInjector in it:
All we have to do now is to inject required dependencies in BaseViewModel class:
Retrieve data in ViewModel
Now that injection of PostApi injection has been done, let’s retrieve the data from the API. We will need to perform the call in background thread while we want to perform actions with the result on Android main thread. To do so, we will use RxAndroid library. In order to add dependency to that library in our project, just add the following lines to the build.gradle file of the module:
Then, go back to the PostListViewModel class as it is now time to write the method to get the results:
ViewModel onCleared()
Now, we would like to be able to dispose subscription property when the ViewModel is no longer used and will be destroyed. Android ViewModel provides the onCleared() method which will be called when this occurs:
LiveData


Now, we will add a MutableLiveData the view will be able to observe in order to update the visibility of the ProgressBar we will show while retrieving the data from the API.
Layout, DataBinding and BindingAdapters
For this part, we will use DataBinding and DataBinders, so we will need to use those libraries in our project. We will also add a ConstraintLayout and RecyclerView for the layout. To add them, let us first specify the version number of the android support library in the project build.gradle file:
Now we can edit the build.gradle file of the module:
Now, we can create a layout file named activity_post_list.xml :
As you can see, we add the attribute app:mutableVisibility="@{viewModel.getLoadingVisibility()}" to the ProgressBar. This attribute does not exist, so we will have to define it with a dedicated BindingAdapter.
To do so, let’s create a file named BindingAdapters.kt in the utils package. In this file, we will define a DataBinder for the mutableVisibility attribute:
Actually, we all dream of View.getParentActivity() method, but it does not exist. So we will have to add an extension function to View class, and to do so, let us create a package named extension in utils package, in which we will create a file named ViewExtension.kt :
PostListActivity
It is now time to create the PostListActivity class:
Manifest
It’s time to add the Activity we just created and the Internet permission to the Manifest to be able to test what we developed so far:
Now you can run the application. What you should see is the ProgressBar appearing and disappearing more or less quickly (depending on your Internet connection).
That’s great, but it would be better to display a list of Posts actually :-).
Handle errors
Now, what we will do is to display an error SnackBar when an error occurs, allowing the user to retry to retrieve the posts. As SnackBar is part of the support design library, we need to add that dependency to the build.gradle file of the module.
Now, we will add the string resources we will use when displaying the error:
Now, let us add a MutableLiveData (for the message of the error) and an OnClickListener (for the action of the error) properties to the ViewModel:
All we have to do now is to observe the value of errorMessage in the PostListActivity to display the SnackBar when it is not null, and hide it when the value is null:
You can now try to run the application in airplane mode, and you should see the ProgressBar then the error Snackbar.
Displaying the list of Posts


Ok, now it is time to do it: display the list of the posts. To do so, we will create a ViewModel for each item of the list. Let’s create a PostViewModel class in the ui.post package:
Now, we can create the layout for the item, which will be named item_post.xml:
Now, we need to edit BindingAdapters.kt in order to add a BindingAdapter for the app:mutableText attribute:
Adapter and ViewModel
Let us create a PostListAdapter class in the ui.post package:
Now let us focus on the ViewHolder class. We know how to get the ViewModel associated to an Activity and because we add the View.getParentActivity() extension method, it would be easy to get the instance of PostViewModel using ViewModelProviders.of(binding.root.getParentActivity()).get(PostViewModel::class.java). The thing is the ViewModel associated to an Activity is a Singleton, so using it would make the list to display the same data to each row.
But because we use MutableLiveData, we do not have to instantiate a new PostViewModel for each row, but only for each instance of ViewHolder :
Setting the adapter to the RecyclerView
Now, all we have to do is to set the PostListAdapter to the RecyclerView, then update data when they are retrieved. To do so, we need first to edit the PostListViewModel class:
Now all we have to do is to set the adapter in the activity_list_post layout (line 26 of the following file):
…then add a BindingAdapter to allow us setting an adapter to the RecyclerView:
You can now run the application and it will show you the list of the post retrieved from the API.
Room


An article about Android Architecture Components would not be complete if it did not cover Room. And an article about MVVM on Android would not be complete if it did not cover how to deal with Context dependent instances in the ViewModel. So here we are.
The aim of this article one more time is to show you how to make everything work together, not to show you how a real application works. So for this part, we will make the most easy thing :
- if there are posts in the database, we show them
- if not, we get them from API and store the result in database
Add dependency
Project build.gradle file:
Module build.gradle file:
Entity
Now, we will update the Post class to make it an @Entity that can be saved in the Database:
Dao
Now, we will add a DAO class to allow us to insert and retrievePosts from the database. To do so, let us add an interface named PostDao in the model package:
Database
We will finally add an AppDatabase class to a package named database in the model package:
Use Context Dependent instances in ViewModel
Now we need to use a PostDao instance in the ViewModel in order to retrieve Post from the database and insert them.
To do so, we will add a PostDao argument to the constructor of PostListViewModel. All we have to do then is to call the insert() and all() methods of the PostDao instance:
ViewModelProvider.Factory
Now, we just need to create a ViewModelFactory class in the injection package to let the ViewModelProvider know how to instantiate our ViewModel:
Then, we need to tell the provider to use this factory to instantiate the PostViewModel class. To do so, update the onCreate() method of PostListActivity :
You can now try the application. Once you have run it one time, you can switch your phone to airplane mode, and the list of post should be displayed on next times you run the application
Summary
So we now have seen a complete implementation of the MVVM architecture with all Android Architecture Components.
The full source code of this project can be found on MVVMPosts repository on GitHub:
If you liked this article, feel free to follow me on Twitter.