Saved State in ViewModels : ViewModel data that survives background process restart

Added in lifecycle-viewmodel-savedstate:1.0.0-alpha01

Both Java and Kotlin

The Challenge of onSaveInstanceState

When ViewModels initially launched, there was a confusing issue involving onSaveInstanceState . Activities and fragments can be destroyed in three ways:

1. You meant to navigate away permanently: The user navigates away or explicitly closes the activity — say by pushing the back button or triggering some code that calls finish() . The activity is permanently gone.

2. There is a configuration change: The user rotates the device or does some other configuration change. The activity needs to be immediately rebuilt.

3. The app is put in the background and its process is killed: This happens when the device is running low on memory and needs to quickly free some up. When the user navigates back to your app, the activity will need to be rebuilt.

In situations 2 and 3, you want to rebuild the activity. ViewModels have always helped handle situation 2 for you, because the ViewModel is not destroyed on a configuration change; but in situation 3, the ViewModel is destroyed as well, so you actually need to save and restore data using the onSaveInstanceState callback in your activity. I go into this tricky distinction in much greater detail in ViewModels: Persistence, onSaveInstanceState(), Restoring UI State and Loaders.

Saved State Module

The ViewModel Saved State module helps you handle that third situation: process death. The ViewModel no longer needs to send and receive state to and from the activity. Instead you now can handle saving and restoring data all within the ViewModel. The ViewModel can now really handle and hold all of its own data.

This is done using a SavedStateHandle, which is very similar to a Bundle; it’s a key-value map of data. This SavedStateHandle “bundle” is in the ViewModel and it survives background process death. Any data you had to save before in onSaveInstanceState can now be saved in the SavedStateHandle. For example, the id of a user is something you might store in the SavedStateHandle.

Setting up Saved State Module

Let’s see how to use the new module. Note that the code shown below is very similar to this code from Step 6 of the Lifecycles Codelab. That code is in Java, the code below is in Kotlin.

Step 1: Add the Dependency

SavedStateHandle is currently in alpha (meaning the API might change and we’re looking for feedback), and it’s a separate library. The dependency to add is:

implementation ‘androidx.lifecycle:lifecycle-viewmodel-savedstate:1.0.0-alpha01’

Note, if you want to keep up with what changes happen in the library, check out the lifecycle release notes page.

Step 2: Update the call to ViewModelProvider

Next, you want to create a type of ViewModel which has a SavedStateHandle. In your activity or fragment’s onCreate , update your call to ViewModelProvider to:

The class that creates ViewModel is a ViewModel factory and there’s a ViewModel factory that makes ViewModels with SavedStateHandles called SavedStateVMFactory. The created ViewModel will now have a SavedStateHandle, associated with the activity/fragment passed in.

Note: The upcoming alpha release of the Androidx activity and fragment libraries will launch in July. In these releases (as noted here), SavedStateVMFactory will become the default ViewModelProvider.Factory when you make a ViewModel in an activity or fragment. This means that if you’re using the newest alpha versions of Androidx activity or fragment, you will not need to add the lifecycle-viewmodel-savedstate dependency or use SavedStateVMFactory explicitly. In short, when this change happens and if you’re using the new alpha versions, you can skip steps 1 and 2, and just go to step 3 below.

Step 3: Use SaveStateHandle in ViewModel

Once you’ve done this, you can use the SavedStateHandle in your ViewModel. Here is an example of keeping a user id in the SavedStateHandle:

Construct: MyViewModel takes in SavedStateHandle as a constructor parameter. Save: The saveNewUser method shows an example of saving data in a SavedStateHandle. You save the key value pair of USER_KEY and then the current userId . As data updates in the ViewModel, it should be saved in the SavedStateHandle. Retrieve: savedStateHandle.get(USER_KEY) is an example of getting the current value saved in the SaveStateHandle.

Now if either the activity is destroyed due to rotation or due to the OS killing your process to free up memory, you can be ensured the SavedStateHandle will have your data.

Usually you will use LiveData in your ViewModel. For that you can use the SavedStateHandle.getLiveData() method. Here’s an example of replacing getCurrentUser with a LiveData, which allows for observation:

To learn more check out Step 6 of the Lifecycles Codelab and the official documentation.