Jetpack Saved State for ViewModel: Getting Started

In this tutorial, you’ll learn how to used the Saved State library from Android Jetpack to preserve the UI state of an Android application. By Ishan Khanna.

Leave a rating/review
Download materials
Save for later

If your app loses user data when the user kills it or switches screens, you’re going to get bad reviews and ratings. To ensure a good experience, you must preserve the footprint, or state, of the app at any point of time. You’ll improve the user’s experience and earn good reviews.

In this tutorial, you’ll develop an app, HopelessHubby, which helps you curate a grocery list. You’ll also learn how to use the Saved State library (part of the Android Jetpack collection of libraries) to preserve your UI state.

By the end of this tutorial, you’ll learn:

  • About UI State and its importance in Android apps.
  • How to simulate system initiated process death.
  • How to implement Saved State for ViewModels.
  • What data types are available for persistence.

Getting Started

You can download the project materials by clicking the Download Materials button at the top or bottom of the tutorial. Then, open the project in Android Studio 3.4 or higher.

You’ll use some ADB commands in this tutorial. If you’re already familiar with them, feel free to skip to the Saving the UI States section below.

What is ADB?

ADB refers to the Android Debug Bridge. It’s a command-line tool that lets you communicate with a device running Android. It’s part of the Android SDK Platform-Tools package.

The adb command lets you perform various actions on a device, such as installing apps and debugging them over USB or WiFi. Since Android is a UNIX-BASED operating system, these adb commands also bring access to a Unix shell running on the device, which lets you run many commands.

If you are interested in learning more about the ADB. Checkout this article on our website.

In order to successfully completely this tutorial you need command line access to the ADB, the next section will guide you on how to verify that.

Verifying Access to ADB

Type adb devices in your terminal and press Enter.

List ADB Devices

The output should start with the text 'List of devices attached'.

If you see that, you’ve access to ADB via the command line.

If you’re interested in other ways to get ADB working on your machine, check out this StackOverflow answer.

Note: If you don’t see that, this article shows you how to configure ADB for command line access.

Saving UI States: The Past

As the operating systems and hardware capabilities of mobile phones have evolved over the years. The responsibility of saving the states has shifted from users to the applications. Remember how you’d always hit Ctrl + S about ten times after each changed you made in any application on your computer.

On mobile, however, it is rare that you are explicitly asked to hit a save button before you close an app or move on to another one.

Creators of Android probably envisioned this paradigm shift even before launching the first version and hence allowed developers to cater to this scenario.

This is the reason onSaveInstanceState() method exists in Android SDK since API level 1. Through this method, the platform allows you to store any information related to the instance of the current activity that you might need when restoring it. Because no code is perfect developers often have to wrap their heads around the problems and strange behaviors this API brings along. Let’s see a couple of them.

Understanding Problems with onSaveInstanceState()

On Android platform versions lower than Build.VERSION_CODES.P there are no guarantees about whether this method will be called before or after onPause(). What is known is that it will be called before onStop() of the Activity’s lifecycle.

On the platforms target version Build.VERSION_CODES.P or higher, however, this method is guaranteed to be called after onStop() of the Activity is called. These ambiguous behaviors are often hard to predict and majority of developers won’t learn about them until they encounter a bug in their app as this information is buried deep inside the documentation.

Another case when onSaveInstanceState() is not called is when the user explicitly closes the Activity or other cases when finish() is called.

Even with some of these caveats this API has survived the test of time and millions of developers still continue to use it.

The Android ecosystem however has evolved at a much faster pace.

With introduction of modern architectures the developers have started separating the business logic from the view itself which means views don’t know how to persist data anymore.

While this is great for the overall health of your codebase, it might affect your user experience if you don’t save the UI states whereever needed.

Although with the modern architectures available today, you can save some state information using this method, the Jetpack library is making it easier for you to do it via the ViewModel itself. In the next section, let us look at the need for saving state and what effects it has on the user experience.

Saving UI States: The Present

If you want to ensure a great user experience, your app needs to preserve and restore its UI state when it experiences system-initiated destruction.

A simple way of balancing the user expectations and system behavior is to use a combination of ViewModel objects, the onSaveInstanceState() method, and/or local storage to persist the UI state across such application and activity instance transitions.

No matter which approach you choose, you should always strive to meet the users’ expectations and provide a better user experience. Your users shouldn’t perceive any delay while loading data onto the UI, especially when a configuration change occurs. For example, they shouldn’t notice any delay when rotating their device from portrait to landscape mode.

Generally speaking, you’ll probably use both ViewModel and onSaveInstanceState().

Understanding User Expectations and System Behavior

Users take various actions as they run an app. For almost every explicit action, users expect feedback or an output.

Think of output in terms of app state. The expectation could be to either clear or preserve it. In some cases, the action the user expects is automatically performed but in others it isn’t.

You can dismiss a UI state in two ways:

  • User-initiated dismissal can occur by tapping the Back button, swiping the activity off of the Overview screen, killing the app, completing any Activity through Activity.finish(), or simply navigating up from the Activity.
  • System-initiated dismissal can occur from a configuration change, such as changing to multi-window mode or a screen rotation.