Jetpack Saved State for ViewModel: Getting Started
- Getting Started
- What is ADB?
- Verifying Access to ADB
- Saving UI States: The Past
- Understanding Problems with onSaveInstanceState()
- Saving UI States: The Present
- Understanding User Expectations and System Behavior
- Simulating Process Death
- Finding the App Process
- Killing the App Process
- Feeling the User Experience
- Handling The Process Death
- Adding the Saved State Library
- Retrieving The ViewModel State With SavedStateHandle
- Saving The ViewModel State With SavedStateHandle
- Instantiating ViewModel With Activity
- Gluing it All Together
- Diving Into Different Types of Data for Persistence
- Identifying Candidates for Using Saved State
- Where to Go From Here?
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.
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
adb devices in your terminal and press Enter.
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.
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
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.