MVVM with Hilt, RxJava 3, Retrofit, Room, Live Data and View Binding

Abhinav Singh
The Startup
Published in
6 min readJun 20, 2020

In this article, we will see how to implement MVVM architecture with Hilt, RxJava, Retrofit, Room, Live Data, and View Binding.

This article is for someone

  • New to Dependency Injection using Hilt
  • Migrating to Hilt from Dagger.

In this project, we will fetch details form a REST API and then use Room to save it offline. Since a number of concepts are being used here we will look at each of them one by one.

If you want to learn about dagger first you can check out this article. It will be helpful for you to understand hilt more easily.

Project structure:

Let's dive into code.

First, add all the required dependencies to your project.

To setup hilt, you can also find the instructions from here.

Setting up API service

To fetch details we are using PokeApi here.

As you can see the return type is Observable will see more about RxJava later in the article.

Our Pokemon and PokemonResponse model class look like this:

Setting up Hilt

Base Application class: This class is necessary for the hilt and you should annotate it with @HiltAndroidApp. Don't forget to add it to the manifest file in the application tag.

<application
android:name=".BaseApplication"

Now we will create a Network module. Now, what is a module? A module is a class that provides information to the hilt about how to provide an instance of a class we don't own. For hilt to instantiate objects for us we use @Inject annotation above the constructor of the class but when where to put the @Inject annotation when we don't own a class or when we are dealing with an interface which doesn't have a constructor in these cases we use @Provide annotation inside the module class to tell hilt to instantiate these objects for us. To setup module create a class NetworkModule and annotate it with @Module annotation now in hilt we have to add one more annotation which is @InsatallIn annotation and we will pass ApplicationComponent here because we want the NetworkModule to be available for us for application scope.

In the module, we will provide a method to get the PokeApiService object. Create a method providePokeApiService of PokeApiService return type and annotate it with @Provide annotation.

Our app will have two fragments one to show the list of pokemon fetched from the API and the second fragment will show the favorites pokemon which we have saved using Room and we will use a button to switch between these fragments.

Setting up Repository

We have used @Inject above the Repository constructor so that whenever we need a Repository object hilt will provide us Repository Object. The Repository class has two dependencies PokeApiService and PokeDao. PokeDao is related to Room ignore it for now we will talk about it later in the article. The important point is if we want hilt to provide us Repository object we also have to tell hilt how to provide an instance of classes or interfaces on which our Repository class depends. We have already created NetworkModule which provides a method to get a PokeApiService object. So when providing us the Repository object hilt will automatically provide all the dependencies of the Repository class.

We have simply created a method getPokemons to return the Observable of PokemonResponse type.

Setting up ViewModel

Here we see a new annotation @ViewModelInject and trust me it is the best thing about using hilt. If you have been using dagger in your projects with MVVM you must have faced the problem of injecting viewmodels. The most famous workaround was to create your own ViewModelFactory class but that was a long and tedious work. But with the hilt, this annotation will do all the work and you can easily inject ViewModels.

Here we have created a method getPokemons. As we know the repository.getPokemons() will return an Observable we will observe it here and then set the pokemonList(Mutable Live Data) to update the fragment of the changes.

RxJava has three basic concepts Observable, Observers, and Operators.

Think of observable as some entity emitting data but what is the benefit of observable emitting data if no one is there to observe it so we have Observers which observes data emitted by the Observables. Operators are something that manipulates the data or transforms the data and passes it to the subscribers.

The subscribeOn(Schedulers.io()) means that we want to subscribe on the background thread and observeOn(AndroidSchedulers.mainThread()) means that we want to observe the data on the main thread. The map operator is used here because we want Pokemon List but we are getting an Observable of PokemonReosponse so we can get the list of pokemon from pokemonResponse.getResults() but we also want to change one more thing. The URL we get from Pokemon Object contains details about the pokemon but we just want the image of the pokemon so we will get the index of the pokemon from this URL and then concatenate it with different URL which will directly provide us the URL for the pokemon image.

Setting up Room

For room setup, we need three things Entity, Dao, and Database.

For Entity, we will update our Pokemon Pojo class as below

For Dao, we will create an interface PokeDao as follows

We have created methods to insert Pokemon in our favorites list, delete pokemon from the list, and get all pokemons from the list.

Now we will create the abstract database class PokemonDB for storing our favorites pokemon.

We have added an abstract method of PokeDao return type.

Now we will create DatabaseModule which will help hilt to provide us with the instance if this database.

We have added the @Module and @InstallIn annotation above this class to tell hilt that this is a module and it is required for application cope.@Singleton is used to have a single instance of this database over the whole app.

Now we will modify our Repository class and PokemonViewModel class.

Till now we have completed setting up Room, Hilt, and the ViewModel. Now we will set up the fragments and activity.

Setting up Fragments and Activities

Home Fragment

We have annotated the fragment with @AndroidEntryPoint which means that hilt should provide all the dependencies to this fragment that it asks for. One important point to be noted:-

If you annotate an Android class with @AndroidEntryPoint, then you also must annotate Android classes that depend on it. For example, if you annotate a fragment, then you must also annotate any activities where you use that fragment.

We have used ItemTouchHelper class for swiping function we will right swipe in the home fragment to add the pokemon to the favorites and left swipe the pokemon item in the favorites to delete them from the favorites list.

Favorites Fragment

We have done the same thing that we have done in the home fragment just change the swiping direction in ItemTouchHelper.

Main Activity

In the activity, we have used the button to change the fragments. As you can see we have used view binding here if you are not familiar with view binding check this it will help you to get your hands on view binding.

Finally, we will run the app now.

You can find the whole code from here.

Now you are able to implement MVVM with Hilt, RxJava, Retrofit, Room LiveData, and View Binding.

If you want to dive further check out my movie’s info app build using Navigation Component and all the tech stacks explained above.

If you find this article useful please share it with your friends.

Let’s connect on LinkedIn, Github, Twitter.

--

--

Abhinav Singh
The Startup

Software Engineer | Linkedin @cachedengineer | Twitter @cached_engineer