UiState Handling with SavedStateHandle

Burak Taşcı
Appcent
Published in
4 min readFeb 21, 2023

Hello everyone, this is Burak from Appcent. I’m working as a full time Android Developer and in this article I will discuss how to save UI state across the Android lifecycle and protect it from system-initiated process kills.

First, let’s review the purpose of ViewModel. ViewModel survives configuration changes such as device rotation, language change, etc. It holds data related to the lifecycle of its fragment/activity and remains until the activity/fragment is completely destroyed (if onDestroy invoked without any configuration change). You can see when the ViewModel is destroyed (onCleared invoked) in the ViewModel lifecycle diagram below.

ViewModel Lifecycle

User-initiated UI state dismissal

User-initiated UI state dismissals are:

  • Swiping the activity off the Overview (Recents) screen
  • Killing or force-quitting the app from the Settings screen
  • Rebooting the device
  • Completing some type of “finishing” action (backed by Activity.finish())

These actions cut off all resources (such as separate RAM storage) to the application. From a user experience perspective, losing application data through these actions does not feel wrong to the user. The user knows the result of their action, as they chose to kill the app.

System-initiated UI state dismissal

Android OS tries its best to keep every running app in RAM, but in some cases, it can’t and must kill processes to free allocated memory. This is how system-initiated UI state dismissal occurs.

For example, imagine you’re using an app and receive a phone call. After answering the call, you expect to return to the app where you left off. However, if the Android OS kills the process, you won’t see the last screen you were on. This is where the SavedStateHandle comes in.

As the documentation states,

SavedStateHandle is a key-value map that allows you to write and retrieve objects from the saved state. These values persist even after the process is killed by the system, and they remain available through the same object.

The SavedStateHandle object is tied to the task stack, not the application process, so if the user does not remove the task through user-initiated UI state dismissals, the SavedStateHandle object’s data will not be lost. A chart showing the methods for preserving UI state and their effect on the user experience is shown below.

Preserving UI state methods and their effect on UX

How to use SavedStateHandle?

We need to add required dependecies for SavedStateHandle module which are Fragment 1.2.0 dependencies or its transitive dependencies Activity 1.1.0 .

Required dependencies

You can just pass the SavedStateHandle object as constructor parameter for a created ViewModel. It won’t change declaration of the viewmodel.

SavedStateHandle module initalization on contructor

We have now injected the SavedStateHandle object into the ViewModel. Let’s use it to save a UI state. Imagine we have a UI state like the one shown below and we change the layout based on it:

Sample UI State

However, we can’t use the class as is, because the SavedStateHandle object uses a key-value map and must be parcelized. We add the @Parcelize annotation and Parcelable interface to prepare it for the SavedStateHandle object.

Note: Don’t forget to add the “kotlin-parcelize” plugin to the module-level gradle file.

Sample Parcelized UI State

We can create the UI state variable and use it to store UI parameters. We can combine it with LiveData or StateFlow. This will give us a chance to connect it with DataBinding.

SavedStatehandle LiveData Usage
Using DataBinding and SavedStateHandle together

These steps will save our application’s UI state from system-initiated process kills. It will increase user experience.

Summary

Developers have a goal to make user-friendly experiences for users. SavedStateHandle module usage is a nice way to enchance this experience.It gives a chance to save important data about user or user’s actions with a simple way.

Thanks for taking time, let’s meet in the comments section for discussions.

--

--