Android ViewModels: simple example

Tram Ho

Introduce

Let’s take a look at a simple app as follows. App displays the results of 1 basketball match.

App has buttons for users to edit results. However, if the user turns the phone, the current score will disappear in a confusing way.

What is happening?
Device rotation is one of several configuration changes an app can make over its lifetime, including the availability of a keyboard and changing the device language. All these configuration changes cause Activity to be canceled and recreated.

This behavior allows us to do things like use a specific layout in the landscape orientation when rotating the device. Unfortunately, it can be a headache for new (and sometimes not so new) programmers.

At Google I / O 2017, the Android Framework team introduced a new set of Architectural Components, one of which addresses this exact rotation problem.

The ViewModel class is designed to store and manage UI-related data in a life-cycle conscious way. This allows data to persist through configuration changes such as screen rotation.

Simple example

There are three steps to setting up and using ViewModel:

  • Separate your data from the UI controller by creating a class that inherits from ViewModel.
  • Establish communication between ViewModel and your UI controller.
  • Use ViewModel in your UI controller.

Step 1: Create class ViewModel

Note: To create a ViewModel, you’ll need to add the correct lifecycle dependency first.

Generally, you will create a ViewModel class for each display in your application. This ViewModel class will hold all the data associated with the screen and have getter and setter functions to store the data.

Doing this separates the code to render the UI, implemented in your Activity and Fragment, from your data, now located in the ViewModel. So let’s create the ViewModel class for an in-app display we are talking about:

Step 2: Link UI and ViewModel

Your UI (Activity or Fragment) needs to know about your ViewModel. This is so that your UI can display data and update data as interactions with the UI occur, such as pressing a button to increase a team’s score in the aforementioned Basketball Scoring App.

However, ViewModels should not have references to Activity, Fragment or Context. Furthermore, ViewModels cannot contain elements that contain references to the UI, such as View, as this will create indirect references to Context.

The reason you shouldn’t host these objects is that ViewModels outlive your specific UIs. If you rotate an Activity three times, you’ve just created three different Activity instances, but you only have one ViewModel.

With the above analysis, let’s create a UI / ViewModel link. You will want to create a member variable for your ViewModel in the UI.

So in onCreate you should call:

Step 3: Use ViewModel in your UI Controller

To access or change UI data, you can now use the data in your ViewModel. Here is an example of the new onCreate function and the method of updating scores by adding a point to team A in the Basketball Score Update App:

ViewModelsProviders.of

The first time the ViewModelProviders.of method is called by MainActivity, it creates a new ViewModel instance. When this method is called back, this happens whenever onCreate is called, it returns the pre-existing ViewModel associated with the MainActivity. This is exactly how to preserve data.

This only works if you pass the correct UI as the first argument. Although you should never store the UI inside the ViewModel, the ViewModel class still keeps track of the associations between the ViewModel and the UI behind the scenes, using the UI you pass as the first argument.

This allows you to have an application that opens up different versions of the same Activity or Fragment, but with different ViewModel information.

Imagine if we expanded this example to get scores for multiple basketball games. The matches are presented in a list, then clicking on a match in the list will open a screen that looks like the current MainActivity, which will be called GameScoreActivity.

For each different game screen you open, if you combine ViewModel and GameScoreActivity in onCreate, it creates a different version of ViewModel. If you rotate one of these screens, the connection to the same ViewModel will be maintained.

Conclude

In this post, we’ve explored the basics of the new ViewModel class. The main things to draw are:

  • The ViewModel class is designed to consciously store and manage UI-related data in a lifecycle way. This allows data to persist through configuration changes such as screen rotation.
  • ViewModels separate UI implementation from your application data.
  • In general, if your monitor in your app has temporary data, you should create a separate ViewModel for that display’s data.
  • The ViewModel lifecycle lasts from when the linked UI was first created until it is completely destroyed.
  • Never store UI or Context in ViewModel. This includes storing a View in ViewModel. Direct or indirect references to the UI will spoil the purpose of separating the UI from the data and could lead to memory leaks.
Share the news now

Source : Viblo