Dagger2 With MVVM, Retrofit & RoomDB in Android Kotlin

PAUL MATHEW
7 min readDec 10, 2022

--

For those who are following my series of Dagger2 for Noob Developers let’s look into how to make use of Dagger2 in a normal Android application .

There are some terms added into this project like MVVM ,Retrofit RoomDB. I’ll give brief explanation to each terms during the time when we add them to the project or when we use them.

MVVM

Very brief about MVVM(MVVM itself is huge topic) . Consdier the above image and I’ll explain how this works. Activity/Fragment shows data to the User and this View part ask ViewModel module of the application for the data to be displayed. And this ViewModel will check the Repository for data and it’s repository’s job to connect Model class or module to the ViewModel module. In the above image RoomDB or Retrofit act as Model or data class. This is how a simple MVVM works.

Let’s Add Dependencies for this project

Module level build.gradle file

One more configuration we need to consider is the sample json api url for this project. https://raw.githubusercontent.com

Create a new package, model

In the package create data class and add it’s property like in the API response.

The above data class is created using the below json. (Not compleated.)

Create a new package,utils

We are planning to use this module to save all the utility modules and classes required for this project.

Now create a Constant object liek below to store the base url for this project.

package com.otherTallguy.dagger2example.utils

object Constants {
const val BASE_URL="https://raw.githubusercontent.com"
}

Create a new package, retrofit

Now create new module called retrofit and store the interface classes required for retrofit.

package com.otherTallguy.dagger2example.retrofit


import com.otherTallguy.dagger2example.model.Country

import retrofit2.Response
import retrofit2.http.GET

interface CountriesApi {

@GET("DevTides/countries/master/countriesV2.json") // this is the end point that we need for this project to get the api response.
suspend fun getCountries(): Response<List<Country>> // we are using coroutines here so making the function suspend.
}

In retrofit if we are calling a get api then we use @GET() annotation . If we are using post api then we use @POST(). I hope you guys know the different annotations used in retrofit and how to use them. If no I can make a standalone tutorial for retrofit.

Create a new package,di

Since we are implementing this project with help of Dagger2 we need to add modules for dagger then components for the dagger . So we create new package di to store all the Dependency Injection related things.

Inside di create a module class NetworkModule.

fun providesRetrofit() is to retrun Retrofit object whereever it needed and you can see the @Provides annotation. That means this function will provide the Retrofit object in the Dagger2 binding places where it needs. And @Singleton will restrict the object creation to one time for the app lifecycle.

Now fun providesCountriesApi(retrofit: Retrofit): CountriesApi

What this function do is it will provide the CountryApi Object to the place where it needed since it is annotaed with @Provides like the previous function.

In the same function you can see there is an object passed into it. That is Retrofit object and Dagger will provide that object for us (only because we made the previous function @Provides).

Now let’s create a component

This is how we create a component class and how you guys knows all the annotations used here.

There main reason why that@Singleton in interface class is that the modules used in the project is scoped module and because of that we need to make our component class @Singleton.

This component is such that it is singleton throughout the application. So we need to create an Application class to initialize the component.

Before doing anything further please build the application to make all the modules and components live.

Let’s create an ApplicationClass

And the manifest file.

So till now what are the things that we have done.

  1. Created model package and added the data class required for retrofit
  2. Created retrofit package and added the interface class to call the end point.
  3. Created di package to store all the Dependecy Injection(here it’s Dagger2) related files. Like module class and the component classes
  4. Created Application class and defined it in the manifest. And the Application class deals with the Component class object creation.

Create Repository package

Inside the repository package create a class to call the api and pass the response.

Create viewmodel package

Create a viewmodel class to access the data (here call the api through retrofit) and pass it into the view(MainActivity)

The above code is enough for creating the viewmodel class. But here we need to pass the Repository object into the viewmodel and inorder to do that let’s create a Factory.

Now let’s change the MainActivity class to add viewmodel and get data

Doing this will call the api and get the data from the api and store it in the viewModel livedata variable.

Now we need to create a UI to show all the list of Countries and it’s capital along with the Flag. For that let’s change the activity xml

item xml for showing the list item.

Here I’m using databinding to show the Country name and Capital name

Now we need to create the adapter class to populate the list.

If you observe the above class there is import missing. It’s a utility module function and what it does are

  1. load the image from url
  2. show the loading animation till the image get’s loaded.

loadImage() is used to load image from url with the help of glide. We have already added the dependency for the glide in the project.

And now lets change the MainActivity file also.

Section 2

In this section we are going to integrate RoomDB into the project to store the data and display it when there is no network (we are not storing the image for the moment). Dependency required are already added into the build.gradle file in the begining.

First step is chnage the data class in the model package like this.

Then create a new module db to store all the RoomDB related things.

Then Create interface class DAO to do all the db related operations like insertion, deletion, selection etc.. . Let’s create the DAO

Now the table is created, interface to access the table is alos created.

Let’s create the DB then. For that create an abstract class extending RoomDatabase() like below

Now we use Dagger here to make the DB singleton or else applicationw will create multiple instance.

Now create module class in di package

Not going deep into the annotations used here. Because all of them are explained in the previous Series . What is module do is dagger will look for this module when it needs an object of CountryDB and if it is available it will provide to place where it needed.

Here comes the use of Factory or Builder in Dagger.

Reason : to provide context into the provideCountryDB() to create the DB

So let’s change the component class.

Now let’s change the Application class also.

Now Dagger have retrofit object and RoomDB object and our job is to pass these obejct into the repository class . We have already passed the Retrofit object so let’s pass the RoomDB object like below.

If we run the application right now we can see the normal behaviour that is the country list. And if go to App Inspection in Android Studio we can see the table getting updated like this.

Dagger2 MultiBinding

We have created factory for the viewmode class to pass the values into the custructor of the viewmodel that we use.

Here we use the viewmodelFactory to pass the object of repository class into the viewmodel that we use.

Suppose our MainViewModel require other parements like the repository cass obejcts. Then the easy method is add the new parameter into the factory class and pass it into the viewmodel class just like how we did.

But is it practically possible if there are changes in the parameteres during the Lifecyle of the app development. ? No right …?

If we implement it like below Dagger2 will provide..

because of the constructor injection method. And we will change the factory class like below to accommodate the change throughout the application.

But consider there is situation where there are n number of screens. In that case we need to create n number of ViewModel classes for each screens and n number of Factory classes for each of the new ViewModels. For this situation Dagger has a solution . MutiBinding…! With that solution we need only one Factory class. So lets look into that solution.

For that create new module

Now make chanege in the Component class to add the new module and get the map that made in the ViewModelModule class.

Now make change in the MainViewModelFactory.

That’s it, we have implemented multiplebinding with dagger.

Full code for the project till now is below.

--

--

PAUL MATHEW

A Noob android developer who try to make some notes which obtained by going through different tutorials and stackoverflow.