How to use onSaveInstanceState() and onRestoreInstanceState()?

Android

Android Problem Overview


I am trying to save data across orientation changes. As demonstrated in the code below, I use onSaveInstanceState() and onRestoreInstanceState(). I try to get the saved value and I check if it is the correct value in onRestoreInstanceState(). But when I try to use the new value in onCreate(), I don't have the new value but the old one.

protected void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
		outState.putString("TEXT", user);

	}
protected void onRestoreInstanceState(Bundle savedInstanceState) {
	super.onRestoreInstanceState(savedInstanceState);
	savedUser = savedInstanceState.getString("TEXT");
	Log.d("enregistred value", savedUser);

}



public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		int display_mode = getResources().getConfiguration().orientation;

		if (display_mode == 1) {

			setContentView(R.layout.main_grid);
			mGrid = (GridView) findViewById(R.id.gridview);
			mGrid.setColumnWidth(95);
			mGrid.setVisibility(0x00000000);
			// mGrid.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);

		} else {
			setContentView(R.layout.main_grid_land);
			mGrid = (GridView) findViewById(R.id.gridview);
			mGrid.setColumnWidth(95);
			Log.d("Mode", "land");
			// mGrid.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);

		}
		Log.d("savedUser", savedUser);
		if (savedUser.equals("admin")) { //value 0
			adapter.setApps(appManager.getApplications());
		} else if (savedUser.equals("prof")) { //value 1
			adapter.setApps(appManager.getTeacherApplications());
		} else {// default value
			appManager = new ApplicationManager(this, getPackageManager());
			appManager.loadApplications(true);
			bindApplications();
	    }
}

Android Solutions


Solution 1 - Android

> When your activity is recreated after it was previously destroyed, you > can recover your saved state from the Bundle that the system passes > your activity. Both the onCreate() and onRestoreInstanceState() > callback methods receive the same Bundle that contains the instance > state information. > > Because the onCreate() method is called whether the system is creating > a new instance of your activity or recreating a previous one, you must > check whether the state Bundle is null before you attempt to read it. > If it is null, then the system is creating a new instance of the > activity, instead of restoring a previous one that was destroyed.

static final String STATE_USER = "user";
private String mUser;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Check whether we're recreating a previously destroyed instance
    if (savedInstanceState != null) {
        // Restore value of members from saved state
        mUser = savedInstanceState.getString(STATE_USER);
    } else {
        // Probably initialize members with default values for a new instance
        mUser = "NewUser";
    }
}
    
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    savedInstanceState.putString(STATE_USER, mUser);
    // Always call the superclass so it can save the view hierarchy state
    super.onSaveInstanceState(savedInstanceState);
}

http://developer.android.com/training/basics/activity-lifecycle/recreating.html

Solution 2 - Android

  • onSaveInstanceState() is a method used to store data before pausing the activity.

Description : Hook allowing a view to generate a representation of its internal state that can later be used to create a new instance with that same state. This state should only contain information that is not persistent or can not be reconstructed later. For example, you will never store your current position on screen because that will be computed again when a new instance of the view is placed in its view hierarchy.

  • onRestoreInstanceState() is method used to retrieve that data back.

Description : This method is called after onStart() when the activity is being re-initialized from a previously saved state, given here in savedInstanceState. Most implementations will simply use onCreate(Bundle) to restore their state, but it is sometimes convenient to do it here after all of the initialization has been done or to allow subclasses to decide whether to use your default implementation. The default implementation of this method performs a restore of any view state that had previously been frozen by onSaveInstanceState(Bundle).

Consider this example here:
You app has 3 edit boxes where user was putting in some info , but he gets a call so if you didn't use the above methods what all he entered will be lost.
So always save the current data in onPause() method of Activity as a bundle & in onResume() method call the onRestoreInstanceState() method .

Please see :

https://stackoverflow.com/questions/6525698/how-to-use-onsavedinstancestate-example-please

http://www.how-to-develop-android-apps.com/tag/onrestoreinstancestate/

Solution 3 - Android

This happens because you use the savedValue in the onCreate() method. The savedValue is updated in onRestoreInstanceState() method, but onRestoreInstanceState() is called after the onCreate() method. You can either:

  1. Update the savedValue in onCreate() method, or
  2. Move the code that use the new savedValue in onRestoreInstanceState() method.

But I suggest you to use the first approach, making the code like this:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    int display_mode = getResources().getConfiguration().orientation;

    if (display_mode == 1) {

        setContentView(R.layout.main_grid);
        mGrid = (GridView) findViewById(R.id.gridview);
        mGrid.setColumnWidth(95);
        mGrid.setVisibility(0x00000000);
        // mGrid.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);

    } else {
        setContentView(R.layout.main_grid_land);
        mGrid = (GridView) findViewById(R.id.gridview);
        mGrid.setColumnWidth(95);
        Log.d("Mode", "land");
        // mGrid.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);

    }
    if (savedInstanceState != null) {
        savedUser = savedInstanceState.getString("TEXT");
    } else {
        savedUser = ""
    }
    Log.d("savedUser", savedUser);
    if (savedUser.equals("admin")) { //value 0
        adapter.setApps(appManager.getApplications());
    } else if (savedUser.equals("prof")) { //value 1
        adapter.setApps(appManager.getTeacherApplications());
    } else {// default value
        appManager = new ApplicationManager(this, getPackageManager());
        appManager.loadApplications(true);
        bindApplications();
    }
}

Solution 4 - Android

In most cases, you should not need to override these methods. If you want to override these , do not forget to call super.onSaveInstanceState / super.onRestoreInstanceState

Important Note from documentation

> The default implementation takes care of most of the UI per-instance > state for you by calling View.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)). If you override this method to > save additional information not captured by each individual view, you > will likely want to call through to the default implementation, > otherwise be prepared to save all of the state of each view yourself.

Check if the information you want to preview is part of a view that may have an ID. Only those with an ID will be preserved automatically.

If you want to Save the attribute of the state which is not being saved already. Then you override these methods and add your bit.

protected void onSaveInstanceState (Bundle outState)

protected void onRestoreInstanceState (Bundle savedInstanceState)

In latest SDK versions Bundle parameter is not null, so onRestoreInstanceState is called only when a savedStateIsAvailable.

However, OnCreate as well gets savedState Parameter. But it can be null first time, so you need to differentiate between first call and calls later on.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionZizouView Question on Stackoverflow
Solution 1 - AndroidArvisView Answer on Stackoverflow
Solution 2 - AndroidShreyos AdikariView Answer on Stackoverflow
Solution 3 - AndroidEric WuView Answer on Stackoverflow
Solution 4 - AndroidSandeep DixitView Answer on Stackoverflow