Sign in Get started
EDITOR'S PICKS TOP 10 STORIES FOR WRITERS SUBMIT STRAIGHT INTO YOUR INBOX
You have 2 free member-only stories left this month. Sign up for Medium and get an extra one
MVVM with Hilt, RxJava 3,
Retrofit, Room, Live Data and
View Binding
Abhinav Singh Follow
Jun 20, 2020 · 6 min read
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.
1 apply plugin: 'com.android.application'
2 apply plugin: 'dagger.hilt.android.plugin'
3
4
5 android {
6 compileSdkVersion 29
7 buildToolsVersion "29.0.2"
8
9 defaultConfig {
10 applicationId "com.example.pokemon"
11 minSdkVersion 19
12 targetSdkVersion 29
13 versionCode 1
14 versionName "1.0"
15 multiDexEnabled true
16
17 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
18 }
19
20 buildTypes {
21 release {
22 minifyEnabled false
23 proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'prog
24 }
25 }
26 compileOptions {
27 sourceCompatibility = 1.8
28 targetCompatibility = 1.8
29 }
30
31 viewBinding {
32 enabled = true
33 }
34
35 }
36
37 dependencies {
38 implementation fileTree(dir: 'libs', include: ['*.jar'])
39
40 def room_version = "2.2.5"
41 def nav_version = "2.3.0-beta01"
42
43 implementation "androidx.recyclerview:recyclerview:1.1.0"
44 implementation "androidx.cardview:cardview:1.0.0"
45 implementation 'com.google.android.material:material:1.1.0'
46 implementation 'com.android.support:multidex:1.0.3'
47
48 // Hilt
49 implementation "com.google.dagger:hilt-android:2.28-alpha"
50 annotationProcessor 'com.google.dagger:hilt-android-compiler:2.28-alpha'
51 implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha01'
52 annotationProcessor 'androidx.hilt:hilt-compiler:1.0.0-alpha01'
53
54 //RxJava
55 implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
56 implementation 'io.reactivex.rxjava3:rxjava:3.0.0'
57
58 // Retrofit
59 implementation 'com.squareup.retrofit2:retrofit:2.9.0'
60 implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
61 implementation "com.github.akarnokd:rxjava3-retrofit-adapter:3.0.0"
62
63 // ViewModel
64 implementation 'androidx.lifecycle:lifecycle-viewmodel:2.2.0'
65
66 // LiveData
67 implementation 'androidx.lifecycle:lifecycle-livedata:2.2.0'
68
69 // Room
70 implementation "androidx.room:room-runtime:$room_version"
71 annotationProcessor "androidx.room:room-compiler:$room_version"
72 implementation "androidx.room:room-rxjava2:$room_version"
73
74 // Navigation
75 implementation "androidx.navigation:navigation-fragment:$nav_version"
76 implementation "androidx.navigation:navigation-ui:$nav_version"
77
78 // Glide
79 implementation 'com.github.bumptech.glide:glide:4.11.0'
80 annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
81
82
83 implementation 'androidx.appcompat:appcompat:1.1.0'
84 implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
85 testImplementation 'junit:junit:4.12'
86 androidTestImplementation 'androidx.test.ext:junit:1.1.1'
87 androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
88 }
build.gradle hosted with ❤ by GitHub view raw
To setup hilt, you can also find the instructions from here.
Setting up API service
To fetch details we are using PokeApi here.
1 package com.example.pokemon.network;
2
3 import com.example.pokemon.model.PokemonResponse;
4
5 import javax.annotation.Generated;
6
7 import io.reactivex.rxjava3.core.Observable;
8 import retrofit2.http.GET;
9
10 public interface PokeApiService {
11
12 @GET("pokemon")
13 Observable<PokemonResponse> getPokemons();
14 }
PokeApiService.java hosted with ❤ by GitHub view raw
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:
1 package com.example.pokemon.model;
2
3 import androidx.room.Entity;
4 import androidx.room.PrimaryKey;
5
6 import io.reactivex.rxjava3.schedulers.Schedulers;
7
8 /**
9 * Created by Abhinav Singh on 17,June,2020
10 */
11 public class Pokemon {
12
13 private int id;
14 private String name;
15
16 private String url;
17
18 public Pokemon(String name, String url) {
19 this.name = name;
20 this.url = url;
21 }
22
23 public String getName() {
24 return name;
25 }
26
27 public void setName(String name) {
28 this.name = name;
29 }
30
31 public String getUrl() {
32 return url;
33 }
34
35 public void setUrl(String url) {
36 this.url = url;
37 }
38
39 public int getId() {
40 return id;
41 }
42
43 public void setId(int id) {
44 this.id = id;
45 }
46 }
Pokemon.java hosted with ❤ by GitHub view raw
1 package com.example.pokemon.model;
2
3 import java.util.ArrayList;
4
5
6 public class PokemonResponse {
7 private Integer count;
8 private String next,previous;
9 private ArrayList<Pokemon> results;
10
11 public PokemonResponse(Integer count, String next, String previous, ArrayList<Pokemo
12 this.count = count;
13 this.next = next;
14 this.previous = previous;
15 this.results = results;
16 }
17
18 public Integer getCount() {
19 return count;
20 }
21
22 public void setCount(Integer count) {
23 this.count = count;
24 }
25
26 public String getNext() {
27 return next;
28 }
29
30 public void setNext(String next) {
31 this.next = next;
32 }
33
34 public String getPrevious() {
35 return previous;
36 }
37
38 public void setPrevious(String previous) {
39 this.previous = previous;
40 }
41
42 public ArrayList<Pokemon> getResults() {
43 return results;
44 }
45
46 public void setResults(ArrayList<Pokemon> results) {
47 this.results = results;
48 }
49 }
PokemonResponse.java hosted with ❤ by GitHub view raw
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"
1 package com.example.pokemon;
2
3 import android.app.Application;
4
5 import dagger.hilt.android.HiltAndroidApp;
6
7 /**
8 * Created by Abhinav Singh on 17,June,2020
9 */
10 @HiltAndroidApp
11 public class BaseApplication extends Application {
12 }
BaseApplication.java hosted with ❤ by GitHub view raw
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.
abhinav0612/Pokemon
Contribute to abhinav0612/Pokemon development by creating an account on GitHub.
github.com
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.
Sign up for Top 10 Stories
By The Startup
Get smarter at building your thing. Subscribe to receive The Startup's top 10 most read
stories — delivered straight into your inbox, once a week. Take a look.
Your email Get this newsletter
By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information
about our privacy practices.
Android AndroidDev Android App Development Clean Code Mobile App Development
839 2
WRITTEN BY
Abhinav Singh Follow
Android Developer
The Startup Follow
Get smarter at building your thing. Follow to join The Startup’s
+8 million monthly readers & +790K followers.
More From Medium
Kotlin: Final variables Kotlin Flow in Staggered Writing An
in anonymous class Android — Process Recyclerview With Integration Test With
Nitesh goyal
asynchronous Multiple Selection in Jetpack Compose
stream Kotlin and Dagger Hilt
Gaurav Goyal in Microsoft Martina Alinda in The Michel Onwordi in Nerd
Mobile Engineering Startup For Tech
Dagger 2 @Binds vs Package visibility in Using Texture Getting Started With
@Provides Android 11 Counters in the Machine Learning in
Elye in Mobile App Yacine Rezgui in Android
Android GPU Android App Using
Development Publication Developers
Inspector TensorFlow
Francesco Carucci in Rahul Ray in The Startup
Android Developers
Learn more. Make Medium yours. Share your thinking.
Medium is an open platform where 170 million readers Follow the writers, publications, and topics that matter If you have a story to tell, knowledge to share, or a
come to find insightful and dynamic thinking. Here, to you, and you’ll see them on your homepage and in perspective to offer — welcome home. It’s easy and
expert and undiscovered voices alike dive into the your inbox. Explore free to post your thinking on any topic. Write on
heart of any topic and bring new ideas to the surface. Medium
Learn more
About Help Legal