Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
135 views

MVVM With Hilt, Rxjava 3, Retrofit, Room, Live Data and View Binding

The document discusses implementing an MVVM architecture app with Hilt dependency injection, RxJava, Retrofit, Room, LiveData, and View Binding. It outlines adding dependencies, setting up the API service to fetch data from a REST API using Retrofit and RxJava, and saving the data offline using Room. The project structure and code snippets are also presented.

Uploaded by

Micha Ale
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
135 views

MVVM With Hilt, Rxjava 3, Retrofit, Room, Live Data and View Binding

The document discusses implementing an MVVM architecture app with Hilt dependency injection, RxJava, Retrofit, Room, LiveData, and View Binding. It outlines adding dependencies, setting up the API service to fetch data from a REST API using Retrofit and RxJava, and saving the data offline using Room. The project structure and code snippets are also presented.

Uploaded by

Micha Ale
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 1

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

You might also like