Skip to content

Most visited

Recently visited


Saving UI States

The way in which you do, or do not, preserve UI state is a crucial part of the user experience. Whether the user rotates the device, the user restarts the app, or the system shuts down the app, it is important that your activity maintain the state a user expects.

In cases where the UI data to preserve is simple and lightweight, you might use onSaveInstanceState() alone to preserve your state data. In cases where you have complex data that you want to preserve, you can use a combination of ViewModel objects, the onSaveInstanceState() method, and persistent local storage.

This page discusses each of these approaches.

Manging simpler cases: onSaveInstanceState()

The onSaveInstanceState() callback is designed to store relatively small amounts of data needed to easily reload the state of UI controller, such as an activity or a fragment, if the system stops and later recreates that controller. This callback is meant to handle two situations:

As both of these cases imply, onSaveInstanceState() is invoked in situations in which the activity is stopped, but not finished, by the system. For example, if the user leaves the app for several hours, and the system ejects the relevant process from memory, the system calls the default implementation of onSaveInstanceState() to save each UI controller that has an ID. Later, when the user returns to the app, the system restores the activity from the saved state.

Note: onSaveInstanceState() is not called when the user explicitly closes the activity or in other cases when finish()is called.

The system automatically saves and restores a lot of UI data for you: The default implementation of onSaveInstanceState() saves information about the state of the activity’s view hierarchy, such as the text in an EditText widget or the scroll position of a ListView widget. You can also save custom data into this bundle by overriding the onSaveInstanceState() callback. If you override this method to save additional information not captured by each individual entity, you should call the default implementation unless you are prepared to save the states of every entity yourself.

onSaveInstanceState() is not designed to store large amounts of data, such as bitmaps, or complex data structures that require lengthy serialization or deserialization. Serialization can consume lots of memory if the objects being serialized are complicated. Because this process happens on the main thread during a configuration change, serialization can cause dropped frames and visual stutter if it takes too long. Therefore, instead of using onSaveInstanceState() for complex data structures, make sure to store such structures in local persistent storage; it's a good idea to store the data as soon as it's created to minimize the chance of losing it. Then, use onSaveInstanceState() to store unique IDs for each of these objects.

The next section of this document provides more details about preserving more complex data.

Managing more complex states: divide and conquer

When you have more complex data structures that you need to preserve when an activity ends, you can efficiently save and restore UI state by dividing the work among several types of storage mechanisms.

There are two general ways a user can leave an activity, leading to two different outcomes the user may expect:

To implement the behavior for complex data structures in either situation, you use local persistence, the ViewModel class, and the onSaveInstanceState() method together. Each of these approaches stores a different type of data used in the activity.

As an example, consider an activity that allows you to search through your library of songs. Here’s how different events should be handled:

When the user adds a song , the ViewModel immediately delegates persisting this data locally. If this newly added song is something that should be shown in the UI, you should also update the data in the ViewModel object to reflect the addition of the song. Remember to do all database inserts off of the main thread.

When the user searches for a song, whatever complex song data you load from the database for the UI Controller should be immediately stored in the ViewModel object. You should also save the search query itself in the ViewModel object.

When the activity goes into the background, the system calls onSaveInstanceState(). You should save the search query in the onSaveInstanceState() bundle. This small amount of data is easy to save. It’s also all the information you need to get the activity back into its current state.

Restoring complex states: reassembling the pieces

When it's time for the user to return to the activity, there are two possible scenarios for recreating the activity:

Note: When an activity is initially created, the onSaveInstanceState() bundle contains no data, and the ViewModel object is empty. When you create the ViewModel object, you pass an empty query, which tells the ViewModel object that there’s no data to load yet. Therefore, the activity starts in an empty state.

Depending on your activity implementation, you might not need to use onSaveInstanceState() at all. For example, a browser might take the user back to the exact webpage they were looking at before they exited the browser. If your activity behaves this way, you can forego using onSaveInstanceState() and instead persist everything locally. In the song-searching example, that might mean persisting the most recent query in Shared Preferences.

Additionally, when you open an activity from an intent, the bundle of extras is delivered to the activity both when the configuration changes and when the system restores the activity. If the search query were passed in as an intent extra, you could use the extras bundle instead of the onSaveInstanceState() bundle.

In either of these scenarios, you’d still use a ViewModel to avoid wasting cycles reloading data from the database during a configuration change.

This site uses cookies to store your preferences for site-specific language and display options.

Get the latest Android developer news and tips that will help you find success on Google Play.

* Required Fields


Follow Google Developers on WeChat

Browse this site in ?

You requested a page in , but your language preference for this site is .

Would you like to change your language preference and browse this site in ? If you want to change your language preference later, use the language menu at the bottom of each page.

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a short survey?
Help us improve the Android developer experience. (Dec 2017 Android Platform & Tools Survey)