android architecture: Part 6: MVVM with LiveData and ViewModel

By | July 8, 2018



Introduction

In part 4, I started with implementing my benchmark movie app in Model-View-ViewModel (MVVM) using RxJava and with no use of Google architecture components (part of Jetpack now). Part 5 is where I first used LiveData as an architecture component, where I showed how LiveData can be used as a simple lifecycle-aware alternative to RxJava for implementing the observer pattern.

The architecture components, however, feature a component for the ViewModel, called ViewModel , as well. This part discusses what special it is about this component that makes it different to any other ViewModel in MVVM.

Therefore, the same movie search app is implemented here using this new component. This is a simple app with which the user can find the name and year of all the movies containing a keyword:

Screenshot of the movie search app

 

Sorry if you are already a reader of the series and see me repeat the description of the app each time in the beginning of each part. I just want each part to be standalone to avoid user’s loosing track by having to switch back and forth between the parts to understand the newest one.

The complete code for this part is in ‘mvvm-architecture_component-liveData&viewModel’ branch of my Github repo.

 

How is Jetpack ViewModel  different than any other ViewModel in MVVM?

Before discussing this, let’s take a look at an issue in the app developed in part 5 which was not using Jetpack ViewModel . The issue appears when rotating the screen:

Search results clears when the device rotates when not using Jetpack ViewModel

 

As the above shows, the search results clears when the screen rotates, which is not a good user experience.

The reason this happens is because of the OS destroying and recreating  MainActivity  each time configuration change happens. This causes any variable in memory to fade away, as such the list of search results needed for the RecyclerView adapter.

(You might be wondering why the text inside the EditText  is still there after rotation. This is because android automatically saves the EditText  content into storage on configuration change and reloads it upon recreation. This is the default and can be removed by setting setEnabled  to false in the XML declaration of the EditText .)

The Jetpack ViewModel helps with keeping every variable inside the ViewModel  related to the Activity  in memory and thus making it persistent to configuration changes.

 

Let’s see some code

The Jetpack ViewModel implementation kicks in by extending it in the ViewModel class. It does not entail implementing any abstract method or interface and is as easy as adding  : ViewModel()  to the existing ViewModel definition.

Here is the MainViewModel  of the movie app extending Jetpack ViewModel :

The instance of the   ViewModel  inherited from the Jetpack ViewModel  needs to be bound to an Activity  so that the OS knows to save the variables states inside it each time configuration change corresponding to the Activity  happens. This enables the OS to restore these variables when recreating the Activity . Instantiating and binding is simply done by adding the following to the onCreate()  of the Activity :

where this  relates to the Activity .

The above way of creating the ViewModel  is applicable when the constructor is empty. What if this is not the case?

I will deal with that when incorporating dependency injection into the code in part 8 of the series. (I know this is part 6 :D)

Here is the complete code:

The Model  is the same as that used in the last part:

Here is how the app looks like in screen rotation after implementing Jetpack ViewModel :

 

Search results persists when the device rotates when using Jetpack ViewModel

 

Is it all ViewModel is there for?

One might argue we can handle configuration changes by storing variables into savedInstanceState bundle in onSaveInstanceState(savedInstanceState:Bundle )  and then restoring it in onRestoreInstanceState(savedInstanceState:Bundle)  or onCreate(savedInstanceState:Bundle) . Then what is the point of having an architecture component just to handle this?

I would say yes, it is possible, but not efficient due to two main reasons:

  • When user interface is complex, the number and types of objects to be stored becomes considerable. Saving and restoring each of them requires implementing Serializable  and preferably Parcelable  before being able to save each to  savedInstanceState bundle and restoring later. Even though making parcelable objects can be done automatically in Android Studio, making a large number of parcelable objects can be error prone, causing NullPointerException when missing even one.
  • The above persistence, including serialization and deserialization, takes place on the device storage which is far less efficient and slower compared to persistence in memory.

 

Bottom line

The Jetpack ViewModel  is really great as we could see here how it helps with restoring variables from memory in configuration changes by adding very few lines of code to an existing MVVM code. The final question now is whether Jetpack ViewModel spares us the serialization/deserializaition we needed to do when not using Jetpack for the same purpose. The answer is still ‘No’ because not all the Activity  destroy and recreation is due to configuration change. There are times such as when the app is in the background and the system is in high need of memory and finds no other way than destroying the process including the  Activity . The Jetpack ViewModel  does not help with this case and some storage persistence such as in savedInstanceState  is necessary because the OS loses track of the state of the variables inside the Activity  when it has to close it due to memory shortage.

Therefore, even though saving to storage is still necessary for some applications to cover the edge cases of unexpected Activity  close, Jetpack ViewModel  prevents from a large number of errors due to not manually saving the state of the Activity during configuration changes, which is much more probable to happen than Activity termination due to memory shortage considering the large memory size of devices today.

In the next part, I will write about another issue in the movie app where LiveData is not enough to handle at its present implementation. So stay tuned!

 

 

 

 

Please help by spreading the word:

4 thoughts on “android architecture: Part 6: MVVM with LiveData and ViewModel

  1. Stefan Wyszyński

    thanks for great articles!! I have read the whole 6 parts and my head exploded and my brain is on the table :D. Thanks for explaining MVC, MVP and MVVM

    Reply
    1. Ali Post author

      It’s great to know you have liked the series, thanks and stay tuned for the rest 🙂

      Reply
  2. Vlad

    I loved your series. The main problem with architectures is not which one is chosen, but that not all developers working on the project are across the implementation requirements, especially for the clean architecture. This is amplified on large projects. I’m sure this series will be really helpful to many developers to clear some of the confusion.

    I am thinking of including your series in the architecture presentation at my workplace. There is only one thing missing though – unit tests are not complete. I was particularly interested to see how you have managed unit tests in MVVM with ViewModel and LiveData. Hope you get some time on your hands to finish that too.

    Reply
    1. Ali Post author

      Thanks a lot for your comment.
      You’re right, unit tests are incomplete and missing for the sixth part of the series. I’ll update that soon.
      I am happy you liked the series though 🙂

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *