Offline first Android App with MVVM, Dagger2, RxJava, LiveData and Room — Part 4

Part4 → Setting up Repository and ViewModel

Carlos Daniel
5 min readMar 10, 2018
Android’s Architecture Components architecture*

Part1 → Setting up Dagger2
Part2 → Setting up Room
Part3 → Setting up Retrofit
Part4 → Setting up Repository and ViewModel
Part 5 → Setting up de List with “infinite” scrolling

Continuing with the series, this new entry is a little bit heavy, because of the things we need to do. For example, we’ll re-write the way in which the http connection is made in addition to include both repository and view model. I’ll try to write it in the simplest way and as mentioned before, this is only one of the several paths that can be followed to achieve our goal.

In the previous article, Retrofit was configured to turn an http API into an interface and along with a helper class with a Retrofit object we created a new connection and could get the data from a given endpoint.

But taking advantage of Dagger2, it’s possible to create a new module which we can name as NetModule to inject all network dependencies and include it into Dagger2’s graph to easily use it within the app. This new module provides all of this (it’s important to add KotlinJsonAdapterFactory when providing Moshi’s object, this to allow a smooth integration between Kotlin and Moshi, get the data from the api and insert it successfully in the database) :

Remember to include this new module within the array of modules in the AppComponent interface:

Also in the app’s Application class when the injection is made the new module has to be included:

Now is time to merge everything we have coded before. A few packaging refactor is made in order to have under the same package tree all classes regarding data sources:

data -> sources -> local | remote

Package tree

We put all the classes associated to Room in local package, and those associated with Retrofit in remote. Then under sources we can create the new repository class (CryptocurrencyRepository). This new class will have the sole responsibility to get the info from the different data sources:

As you can see, RxJava is the boss in the repo class, besides, for this particular purpose I’m not using Repository and UseCases together but only Repository. Initially, I will do the call to the API to get the results, then they are inserted into the DB and with the operator concatArray get the results from the DB plus the ones additional gotten from the network call. In the future (in another entry), the idea is to do a check to verify if there is a connection, and then get the data and update the DB, otherwise, get the last info from the DB, just to achieve the goal: offline first apps

¿And what about the ViewModel class?

The next layer in order to link the flow between the data sources and the view (the activity) is the ViewModel. The ViewModel in our case, will receive the data from the repository and arrange to send it to the the activity. Here a new actor comes to the scene: LiveData, then new MutableLiveData objects are created and the data, either the list of cryptocurrencies or an error is set to be shown in the view. It’s important to highlight, that we can set the data to a LiveData object through “value” or “postValue” methods. I used the latter in the ViewModel because the way I’m getting the data (this is in another background thread).

I’d like to share here an important used strategy in the ViewModel in order to avoid weird behaviours when getting the data from the DB and the API, a debounce() operator from RxJava was used in order to give a better user experience: having a connection if the API call is executed fast, maybe you don’t want to display the DB items, and then quickly change them with the new items. This is better explained in an Ovidiu Latcu’s article.

… and how to show the data?

Finally, before we can show the data in the activity class, as our ViewModel class doesn’t have an empty constructor we need to implement a ViewModelProvider.Factory and pass it as parameter of the ViewModelProviders, then CryptocurrenciesViewModel is created and the call to get the cryptocurrencies is made and the LiveData (observers) are also implemented:

Before finish the article, I’d also like to share a couple of things I had to do in order to fix some issues when getting the data from the API and showing the info (amount of items) in the screen. As we change the POJO — Entity, we also will need to change the database version because the change of the DB schema also changes. At the same time, Room requires to have a “migration plan” indicating the changes between versions (also to avoid data loss) and add it/them in the database builder. This is the proper path, but if you don’t want to keep the data and avoid the migrations, fallbackToDestructiveMigration() method can be used.

In our case this can be seen in the AppModule class (if you want to have a more clear idea about this, I recommend reading this Florina’s article to understand Room migrations:

Clean the project, rebuild, run it and this branch is done with Repository and ViewModel configurations. :)

You can get the code from Github:

*Headline image taken from Developer Android

--

--

Carlos Daniel

Android & Flutter Developer. GDE for Android & Mobile Engineer.