Categories
android android-activity application-state

How can I save an activity state using the save instance state?

2815

I’ve been working on the Android SDK platform, and it is a little unclear how to save an application’s state. So given this minor re-tooling of the ‘Hello, Android’ example:

package com.android.hello;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class HelloAndroid extends Activity {

  private TextView mTextView = null;

  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mTextView = new TextView(this);

    if (savedInstanceState == null) {
       mTextView.setText("Welcome to HelloAndroid!");
    } else {
       mTextView.setText("Welcome back.");
    }

    setContentView(mTextView);
  }
}

I thought it would be enough for the simplest case, but it always responds with the first message, no matter how I navigate away from the app.

I’m sure the solution is as simple as overriding onPause or something like that, but I’ve been poking away in the documentation for 30 minutes or so and haven’t found anything obvious.

6

  • 9

    When is savedInstanceState == null and when is it not null ?

    Dec 29, 2013 at 0:50

  • 100

    You’re explicitly destroying your activity by – as you said, navigating away from it, such as by pressing back. Actually, the scenario in which this ‘savedInstanceState’ is used, is when Android destroys your activity for recreation. For intance: If you change the language of your phone while the activity was running (and so different resources from your project need to be loaded). Another very common scenario is when you rotate your phone to the side so that the activity is recreated and displayed in landscape.

    – villoren

    Jan 3, 2014 at 19:51

  • 18

    To get the second message, enable “Don’t keep activities” in dev options. Press a home button and get back from recents.

    Feb 7, 2014 at 18:34


  • 5

    this is quite helpful developer.android.com/training/basics/activity-lifecycle/…

    Jul 14, 2015 at 7:00

  • 6

    you can do it with : onSaveInstanceState(Bundle savedInstanceState)

    Sep 4, 2016 at 4:35

2695

You need to override onSaveInstanceState(Bundle savedInstanceState) and write the application state values you want to change to the Bundle parameter like this:

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
  super.onSaveInstanceState(savedInstanceState);
  // Save UI state changes to the savedInstanceState.
  // This bundle will be passed to onCreate if the process is
  // killed and restarted.
  savedInstanceState.putBoolean("MyBoolean", true);
  savedInstanceState.putDouble("myDouble", 1.9);
  savedInstanceState.putInt("MyInt", 1);
  savedInstanceState.putString("MyString", "Welcome back to Android");
  // etc.
}

The Bundle is essentially a way of storing a NVP (“Name-Value Pair”) map, and it will get passed in to onCreate() and also onRestoreInstanceState() where you would then extract the values from activity like this:

@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
  super.onRestoreInstanceState(savedInstanceState);
  // Restore UI state from the savedInstanceState.
  // This bundle has also been passed to onCreate.
  boolean myBoolean = savedInstanceState.getBoolean("MyBoolean");
  double myDouble = savedInstanceState.getDouble("myDouble");
  int myInt = savedInstanceState.getInt("MyInt");
  String myString = savedInstanceState.getString("MyString");
}

Or from a fragment.

@Override
public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
    super.onViewStateRestored(savedInstanceState);
    // Restore UI state from the savedInstanceState.
    // This bundle has also been passed to onCreate.
    boolean myBoolean = savedInstanceState.getBoolean("MyBoolean");
    double myDouble = savedInstanceState.getDouble("myDouble");
    int myInt = savedInstanceState.getInt("MyInt");
    String myString = savedInstanceState.getString("MyString");
}

You would usually use this technique to store instance values for your application (selections, unsaved text, etc.).

20

  • 30

    Any chance this works on the phone, but not in the emulator? I cannot seem to get a non-null savedInstanceState.

    – Adam Jack

    Nov 18, 2009 at 22:39

  • 511

    CAREFUL: you need to call super.onSaveInstanceState(savedInstanceState) before adding your values to the Bundle, or they will get wiped out on that call (Droid X Android 2.2).

    Apr 13, 2011 at 18:59

  • 130

    Careful: the official documentation states, that you should save important information within the onPause-Method because the onsaveinstance-method is not part of the android lifecycle. developer.android.com/reference/android/app/Activity.html

    – schlingel

    Jun 19, 2012 at 7:40

  • 39

    That fact effectively makes onSaveInstanceState almost useless except just for case of screen orientation changes. In almost all other cases, you can never rely on it and will need to manually save your UI state somewhere else. Or preventing your app from being killed by overriding BACK button behavior. I don’t understand why they even implemented it like this in the first place. Totally unintuitive. And you can’t have that Bundle the system give you to save things into except in this very particular method.

    – chakrit

    Jul 5, 2013 at 11:25

  • 17

    Note that saving / restoring UI state to / from the Bundle is automatically taken care of for Views that have been assigned ids. From the onSaveInstanceState docs: “The default implementation takes care of most of the UI per-instance state for you by calling onSaveInstanceState() on each view in the hierarchy that has an id, and by saving the id of the currently focused view (all of which is restored by the default implementation of onRestoreInstanceState(Bundle))”

    Jun 24, 2015 at 23:15


455

The savedInstanceState is only for saving state associated with a current instance of an Activity, for example current navigation or selection info, so that if Android destroys and recreates an Activity, it can come back as it was before. See the documentation for onCreate and onSaveInstanceState

For more long lived state, consider using a SQLite database, a file, or preferences. See Saving Persistent State.

3

  • 5

    When is savedInstanceState == null and when is it not null ?

    Dec 29, 2013 at 22:20

  • 7

    savedInstanceState is null when the system is creating a new instance of your Activity and not null when it’s restoring.

    Jan 15, 2014 at 13:21

  • 8

    … which raises the question of when does the system need to create a new instance of Activity. Some ways of exiting an app don’t create a bundle, so a new instance must be created. This is the fundamental problem; it means one cannot rely on existence of bundle, and must do some alternative means of persistent storage. The benefit of onSave/onRestoreInstanceState is that it is a mechanism the system can do abruptly, without consuming much system resources. So it is good to support that, as well as have persistent storage for more graceful exit from app.

    Sep 19, 2015 at 10:24


444

Note that it is not safe to use onSaveInstanceState and onRestoreInstanceState for persistent data, according to the documentation on Activity.

The document states (in the ‘Activity Lifecycle’ section):

Note that it is important to save
persistent data in onPause() instead
of onSaveInstanceState(Bundle)
because the later is not part of the
lifecycle callbacks, so will not be
called in every situation as described
in its documentation.

In other words, put your save/restore code for persistent data in onPause() and onResume()!

For further clarification, here’s the onSaveInstanceState() documentation:

This method is called before an activity may be killed so that when it
comes back some time in the future it can restore its state. For
example, if activity B is launched in front of activity A, and at some
point activity A is killed to reclaim resources, activity A will have
a chance to save the current state of its user interface via this
method so that when the user returns to activity A, the state of the
user interface can be restored via onCreate(Bundle) or
onRestoreInstanceState(Bundle).

12

  • 58

    Just to nitpick: it’s not unsafe either. This just depends on what you want to preserve and for how long, which @Bernard isn’t entirely clear on in his original question. InstanceState is perfect for preserving the current UI state (data entered into controls, current positions in lists and so forth), whereas Pause/Resume is the only possibility for long term persistent storage.

    Jun 24, 2010 at 14:01

  • 31

    This should be downvoted. It’s not safe to use on(Save|Restore)InstanceState like lifecycle methods (i.e. do anything else in them than save / restore the state). They’re perfectly good for saving / restoring state. Also, how do you want to save / restore state in onPause and onResume? You don’t get Bundles in those methods that you can use, so you’d have to employ some other state-saving, in databases, files, etc. which is stupid.

    – Felix

    Jul 11, 2010 at 10:10


  • 148

    We should not down vote this person at least he made efforts to go through the documentation and I think we people are here for actually building a knowledgeable community and help each other not to DOWN VOTE. so 1 vote up for the effort and I’ll request you people not to down vote rather vote up or don’t vote…. this person clear the confusion that one would like to have when going through documentation. 1 vote up 🙂

    – AZ_

    Nov 26, 2010 at 5:13

  • 21

    I dont think this answer deserves a downvote. Atleast he made an effort to answer and had quoted a section from doco.

    – GSree

    Jan 5, 2011 at 4:54

  • 36

    This answer is absolutely correct and deserves UP vote, not down! Let me clarify difference between states for those guys who don’t see it. A GUI state, like selected radio-buttons and some text in the input field, is much less important than the data state, like records added to a list displayed in a ListView. The latter must be stored to the database in onPause because it’s the only guarantied call. If you put it in onSaveInstanceState instead, you risk loosing data if that is not called. But if the radio-button selection is not saved for the same reason – it’s not a big deal.

    – JBM

    Jun 16, 2011 at 15:15