Lesson 70. onSaveInstanceState. Saving Activity data when rotating the screen

Lesson 70. onSaveInstanceState. Saving Activity data when rotating the screen


In this lesson:

– save the data when you rotate the screen

The theory on this issue can be read here. I will here briefly give a free translation.

When Activity is paused (onPause or onStop), It stays in memory and stores all its objects and their values. And when you return to Activity, everything remains as it was. But if paused Activity is destroyed, for example, when there is a lack of memory, then all its objects are deleted accordingly. And if you go back to it, then the system needs to recreate it and restore the data that was lost during the destruction. For these purposes, Activity provides us with a couple of methods to implement: the first allows us to save data – onSaveInstanceState, and the second – restore – onRestoreInstanceState.

These methods are used when the Activity is destroyed, but it is likely that it will still be required in its current state. That is, when memory is low or when the screen is rotated. If you just pressed the Back button and thus explicitly closed the Activity, then these methods will not be executed.

But even if you do not implement these methods, they have a default implementation that will save and restore the data in the screen components. This is true for all screen components that have an ID.

Let’s create a simple application to protest all these theses. Let’s see at what point these methods are called, let’s try to keep something in them. We also make sure that the appropriate superclass methods are called to store the on-screen component data.

Since we will need to rotate the screen, use when designing Android 2.2. In AVD version 2.3, the rotation is buggy.

Let’s create a project:

Project name: P0701_SaveInstanceState
Build Target: Android 2.2
Application name: SaveInstanceState
Package name: ru.startandroid.develop.p0701saveinstancestate
Create Activity: MainActivity

IN strings.xml write down the texts:



    SaveInstanceState
    Count

IN main.xml draw a button and a couple of boxes for text input:



    
    
        
        
    
    
    

Note that the second EditText without ID.

IN MainActivity we will call all Lifecycle methods and the two above:

package ru.startandroid.develop.p0701saveinstancestate;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

public class MainActivity extends Activity {

  final String LOG_TAG = "myLogs";
  int cnt = 0;

  /** Called when the activity is first created. */
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    Log.d(LOG_TAG, "onCreate");
  }

  protected void onDestroy() {
    super.onDestroy();
    Log.d(LOG_TAG, "onDestroy");
  }

  protected void onPause() {
    super.onPause();
    Log.d(LOG_TAG, "onPause");
  }

  protected void onRestart() {
    super.onRestart();
    Log.d(LOG_TAG, "onRestart");
  }

  protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    Log.d(LOG_TAG, "onRestoreInstanceState");
  }

  protected void onResume() {
    super.onResume();
    Log.d(LOG_TAG, "onResume ");
  }

  protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    Log.d(LOG_TAG, "onSaveInstanceState");
  }

  protected void onStart() {
    super.onStart();
    Log.d(LOG_TAG, "onStart");
  }

  protected void onStop() {
    super.onStop();
    Log.d(LOG_TAG, "onStop");
  }

  public void onclick(View v) {
  }
}

In each of them we write a log to track the sequence of calls. method onclick not yet implemented.

We’ll save everything and run it. Enter some text data into the text boxes:

and return the CTRL + F12 screen.

As a result, we see:

The data in the first field was preserved when rotated, and in the second field were missing. This is because default save / restore methods can only work with components that have ID. Let’s see the log.

onCreate
onStart
onResume

These three methods were executed at startup.

Then we returned the screen:

onSaveInstanceState
onPause
onStop
onDestroy
onCreate
onStart
onRestoreInstanceState
onResume

First of all called onSaveInstanceState, This is where we need to implement saving our data. Next is the destruction of Activity (onPause, onStop, onDestroy) And creating a new one onCreate, onStart. And before onResume the data recovery method is called – onRestoreInstanceState.

The sequence we looked at – stored data before onPause, and restored before onResume. Let’s try to save and restore something now. We have a button on the screen, we will increase the click counter by one click and display a pop-up message with the total number of clicks. The variable cnt we already have. We are implementing onclick:

  public void onclick(View v) {
    Toast.makeText(this, "Count = " + ++cnt, Toast.LENGTH_SHORT).show();
  }

Let’s turn the emulator back to the vertical orientation. Let’s launch the application and click on the button Count. We see a message with a number of clicks. Click a few more times to get, for example, 5.

Now turn the screen and press the button again.

We see that the counter has dropped.

This is due to the fact that the current object Activity was destroyed and lost the value of all variables, including cnt. When you create a new Activity, the value of cnt is 0 and the count is restarted. Let’s fix it. We implement the save method onSaveInstanceState:

  protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putInt("count", cnt);
    Log.d(LOG_TAG, "onSaveInstanceState");
  }

In the object outState we write the value of the variable cnt. The mechanism is similar to data placement in Intent.

method of recovery onRestoreInstanceState:

  protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    cnt = savedInstanceState.getInt("count");
    Log.d(LOG_TAG, "onRestoreInstanceState");
  }

with savedInstanceState we extract the value and put it in a variable cnt. Now while destroying and replaying the Activity variable cnt will retain its value and our counter will continue to work.

Let’s check. Let’s return AVD to vertical orientation. Save everything, launch the application. Push the button, slightly twist the counter

and rotate the screen.

Click the button again

the counter did not reset, but continued to increase from the last position.

So, methods onSaveInstanceState and onRestoreInstanceState defaults store data in screen components. If we implement them independently, then we call super-class methods and write our code for our variables. For the sake of interest, you can try to remove superclass method calls from onSaveInstanceState and onRestoreInstanceState. The data in the text box will no longer be saved when you rotate the screen.

In addition to the onRestoreInstanceState method, you can also access stored data in the onCreate method. Entered the same Bundle. If nothing is restored, it will be = null.

There is another useful mechanism for storing data. Android allows us to save a link to any object and return it to a newly created Activity. There are methods for this:

onRetainNonConfigurationInstance – we store a link in it, passing it to the output of the method

getLastNonConfigurationInstance – this method of reference returns us

That is, for example, we have some object myObj (class MyObject) and we need to keep a reference to it when rotating the screen.

We implement the Activity method onRetainNonConfigurationInstance:

  public Object onRetainNonConfigurationInstance() {
    return myObj;
  }

This method will be called before destroying the Activity. We are required to output this method to our object, which must be stored.

And, when creating a new Activity, onCreate (for example) we use a method getLastNonConfigurationInstance:

myObj = (MyObject) getLastNonConfigurationInstance();

We got the Object class back and brought it to our MyObject class.

In the next lesson:

– we use Preferences to work with the settings of the application




Discuss in the forum [69 replies]

Leave a Comment