Refactor with the new ViewModel class

Saturday, May 27, 2017| Tags: android

Note: Article updated to the latest Architecture Components version, and added clarifications for onSaveInstanceState.

I use Lara Martin’s android_book_listing project to try different architecture patterns. I have a branch using MVP, a branch using MVVM and one branch with MVP + Dagger.

So I thought it would be a good idea to do a new one using the Architecture Components presented at Google I/O 2017.

This is a beginner friendly article.

Starting Code

Before we start, please take a look at the original MainActivity.java. It is a very simple example in which all the calls to Retrofit are made inside the Activity and the configuration changes are handled manually.

Our goal with using ViewModel is:

  • Use the new LiveData to store the response into the new ViewModel and survive configuration changes thanks to the new LifecycleActivity.
  • Let the ViewModel handle keeping the search results on the screen when a configuration change happens (like a screen rotation change).

Note: The ViewModel will not restore the screen state when the process stops, we still need to handle that case with onSaveInstanceState.

Quoting the Google Developers blogpost: https://medium.com/google-developers/viewmodels-persistence-onsaveinstancestate-restoring-ui-state-and-loaders-fc7cc4a6c090

onSaveInstanceState is used for storing a small amount of data needed to easily reload activity state if the UI Controller is stopped and recreated by the system.[…]
Example: The most recent search query

  • Although not mandatory, we will move all Retrofit code into the ViewModel. A proper solution would be to move Retrofit into a Model class and make this a full MVVM app.

Configuration

Add the new maven Google repository to the build.gradle.

allprojects {
repositories {
jcenter()
maven { url ‘https://maven.google.com’ }
}
}

Then add the dependency to the Lifecycle Architecture Components library, which contain the new ViewModel.

compile “android.arch.lifecycle:runtime:1.1.1”
compile “android.arch.lifecycle:extensions:1.1.1”
annotationProcessor “android.arch.lifecycle:compiler:1.1.1”

Creating a ViewModel class

Our first step will be to create a ViewModel, in this case BooksViewModel

The API response will be stored in the MutableLiveData books object, we will update its contents by calling books.setValue() with the API response content.

Now we can use the new ViewModel on the MainActivity onCreate method:

The ViewModelProviders will create a new instance of the BooksViewModel for us if required, and we just need to listen (observe) for data changes in it.

As you can see, you are not calling new BooksViewModel(); so if you need to pass constructor parameters, check Danny Preussler’s article Add the new ViewModel to your MVVM where he explains how to use a Factory to create the ViewModel instances.

Note: In the sample code I did change from AppCompatActivity to LifecycleActivity, this is no longer required in recent versions of the Architecture Components library.

Finish the ViewModel

Time to add the API calls to the ViewModel.

Inside loadBooks we will perform the API call that will update the MutableLiveData with the new content.

Now from the MainActivity, call to model.loadBooks(query) to update the ViewModel.

private void performSearch() {
String formatUserInput
= getUserInput().trim().replaceAll("\\s+", “+”); model.loadBooks(formatUserInput);
}

Once you get the response and update the MutableLiveData, you will get a call on the onChanged method in the MainActivity.

The data inside the BooksViewModel will survive the Activity lifecycle, each time the Activity gets recreated, the onChanged method will be called with the previous data, as far as the process is still alive.

To learn more about handling saving/restoring the screen state and what to do on each chase, check the following article:

ViewModels: Persistence, onSaveInstanceState(), Restoring UI State and Loaders
_Introduction_medium.com

See the full example here in the refactor/ViewModel branch:

miquelbeltran/android_book_listing
_android_book_listing - Example project to help @laramartin understand Retrofit_github.com

Want to learn more Android and Flutter? Check my courses here.

INTERESTED IN WORKING TOGETHER?

Contact with me