How the ViewModel works in Android

Tram Ho

According to the documentation from Android :

“Android architecture components are a collection of libraries that help you to build robust, testable, and maintainable apps.”

In Android architecture components there are many other components including classes used to manage the life cycle of UI components to handle data persistence.

“Managing your UI component lifecycle and handling data persistence”

In this article I will introduce you about ViewModel and how to use it.

General introduction

ViewModel is a class that is responsible for preparing and managing data for a UI component (be it Activity or Fragment). It also provides a way to easily communicate between activity and fragment or between fragments.

ViewModel always created in the same scope (a fragment or an activity) and will be retained until the scope is “alive”. In other words, the ViewModel will not be destroyed when its activity or fragment is destroyed by a configuration change (such as rotating the screen). These owners’ new instances will only reconnect to its existing ViewModel .

ViewModel life cycle (Reference: https://developer.android.com/topic/libraries/architecture/viewmodel )

The main purpose of the ViewModel is to get and keep the information needed for activity and fragment. In addition, activity and fragment can observe changes in ViewModel through the use of LiveData or DataBinding .

ViewModel only responsible for managing the data for the UI so it never accesses the view hierarchy or keeps references to activity or fragment.

We will start with learning about the benefits of using ViewModel

Benefit

  1. ViewModel exists when screen recording or other configuration changes.
  2. ViewModel still running while the activity is in the back stack.
  3. ViewModel is lifecycle-aware.
  4. ViewModel with the support of LiveData can respond to UI changes. Each time the data changes, the UI will be updated based on the LiveData observation with the current data in the ViewModel .
  5. ViewModel easy to understand and easy to test.

In this article, I will introduce to you three important aspects of ViewModel .

  1. Create and use basic ViewModel .
  2. Create and use ViewModel with parameters using ViewmodelProvide.Factory .
  3. Shared ViewModel for communication between activity and fragment.

Simple ViewModel

There are 4 main steps to creating and using ViewModel :

  1. Add dependencies to app-level build.gradle .
  2. Separate data with activity by creating a class that inherits ViewModel .
  3. Create the ViewModel instance in the activity.
  4. Establish communication between ViewModel and View .

Add the dependencies

To use ViewModel we have to add dependencies to app/build.gradle

Or if you are using Kotlin vs AndroidX then add:

Create ViewModel class

To create a SampleViewModel for Activity without any data, we just need to inherit from ViewModel .

onCleared() : Will be called when the ViewModel no longer in use and will be destroyed. It is useful when ViewModel observe some data, and you need to clear them to avoid ViewModel leak.

Create the ViewModel instance in the activity

To create ViewModel in actitvity we will use ViewModelProvider . We need to pass the Context and class name of ViewModel to the ViewModelProvider to get its instance.

ViewModelProvider is a utility to get instance of ViewModel in ViewModelStore . It will return an instance of ViewModel if it exists otherwise it will create a new one. ViewModelStore will store ViewModel by using HashMap .

Establish communication between ViewModel and View

Now we will start with how to get values ​​from ViewModel and put them into View . First, we will create a LiveData in the ViewModel , and when we click on the button we will update its value and show toast message.

Now we will start UI code in Activity.

Every time the data changes on badgeCount via LiveData , we will receive a callback via the registered Observer , so our UI is always updated and gets the latest value.

We have finished creating the ViewModel and communicating it with the activity. The following we will continue with ViewModelProvider.Factory .

ViewModelProvider.Factory

As above, our ViewModel does not accept any parameters, it is easy to do. However, what if we need to pass a parameter to the ViewModel ?

If we do the above, the result will be compile-time error.

so we will need the ViewModelFactory to do this.

ViewModelProvider() creates a default ViewModelProvider.Factory , with this ViewModelProvider.Factory we will not be able to create ViewModel with parameters. So when we add parameters to the ViewModel constructor, the implementation of ViewModelProvider.Factory will fail because it will call the primary constructor for creating the instance of ViewModel .

ViewModelProvider.Factory is the implementation of the factory interface, responsible for initializing ViewModel . We need to re-implement the factory to be able to create a ViewModel with parameters.

To do this, we will inherit from ViewModelProvider.Factory and override the create() which will create an instance of ViewModel .

modelClass.getConstructor(String::class.java) will get a constructor of type String and create an instance of ViewModel by calling newInstance() and passing constructor value into this method.

Now we will do it in the activity

If your ViewModel has a dependency or a parameter and you want to create an instance of it, you need to create a custom ViewModelProvider.Factory to pass that dependency or parameter.

If you simply need to use it via ViewModelProvider(this) to create an instance of ViewModel .

Shared ViewModel for communication between activity and fragment

To communicate between different fragments, or between fragments and activities, we often use interfaces or target fragments. But it’s easier when we share a ViewModel within the activity scope.

To complete the above flow, we need to create the ViewModel instance used in the activity scope in the fragment, the activity will have only one instance created and shared with different fragments.

Problem

Communication between two or more fragments in the same activity is very common.

Assuming we have 2 fragments: Fragment1 allows the user to select an item from the list, Fragment2 will display the content of the selected item. In this case both fragments will define several interfaces to activity bind them together. In addition, both fragments must handle the task when either fragment has not been created or visible.

Solution

To solve the above problem we will share a ViewModel for these fragments within the activity scope.

Now we will create a SharedViewModel class

Assuming we have 2 fragments: Fragment1 and Fragment2 attached in the main activity, we need to post something from Fragment1 to Fragment2 via a clicked button.

ViewModelProvider will return these two fragments together with an instance of SharedViewModel in the activity scope.

This approach offers the following benefits:

  • Activity does not need to do anything about this communication.
  • Fragments don’t need to know each other, they just need SharedViewModel . When one fragment is disappears, the other fragment will function normally.
  • Each fragment is active with its own life cycle, and is not affected by other fragments. So, if a fragment is replaced, the UI continues to work without any problems.

So, we are done communicating between UI components.

Refer

  1. https://medium.com/better-programming/everything-to-understand-about-viewmodel-400e8e637a58
Share the news now

Source : Viblo