Android onSaveInstanceState onRestoreInstanceState

Filed Under: Android

In this tutorial, we’ll be discussing the two vital methods for managing the state of the application, namely onSaveInstanceState and onRestoreInstanceState.
We’ll be developing a Counter Android Application in which we’ll handle the state of the application when the configuration changes.

Android Lifecycle

Following is the lifecycle of the Activities in our application:

android lifecycle

Whenever there is a configuration change, such as rotation or application going into multi-window mode, the activity is recreated.

In this recreation, the application gets restarted and may lose data in the views if not handled properly.

For this there are two methods that are triggered at different stages of the lifecycle:

  • onSaveInstanceState
  • onRestoreInstanceState

They are used to save and retrieve values. The values are stored in the form of a key-value pair.
Let’s look at each of them separately.

onSaveInstanceState

onSaveInstanceState method gets called typically before/after onStop() is called. This varies from Android version to version. In the older versions it used to get before onStop().

Inside this method, we save the important values in the Bundle in the form of key value pairs.

The onSaveInstanceState method looks like :


@Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
    }

On the outState bundle instance we add the key value pairs. Following are the methods applicable:

android onsaveinstancestate methods

We can pass custom class instances by setting the class as Parcelable or Serializable.

Let’s look at an example using Parcelable since it is faster than Serializable.

Following is a custom class :


public class Model implements Parcelable {
        public long id;
        public String name;

        public Model(long id, String name) {
            this.id = id;
            this.name = name;
        }

        protected Model(Parcel in) {
            id = in.readLong();
            name = in.readString();
        }

        public final Creator<Model> CREATOR = new Creator() {
            @Override
            public Model createFromParcel(Parcel in) {
                return new Model(in);
            }

            @Override
            public Model[] newArray(int size) {
                return new Model[size];
            }
        };

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel parcel, int i) {
            parcel.writeLong(id);
            parcel.writeString(name);
        }
    }

writeToParcel method is where we set the class properties on the Parcelable instance.

Now create an instance of the Model and save it in onSaveInstanceState.



Model model = new Model(10, "Hello");

@Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putParcelable("parcelable", model);
    }

Now we can retrieve these saved values in the onRestoreInstanceState method.

Note: onSaveInstanceState gets called whenever you press the home button in your application as well.

Another note: Things like EditText can save and restore their content implicitly provided you’ve set an id on the View. Activity will automatically collect View’s State from every single View in the View hierarchy.


onRestoreInstanceState

This method gets triggered only when something was saved in onSaveInstanceState method.
It gets called after onStart().


@Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        Model model = savedInstanceState.getParcelable("parcelable");
    }

Following are the other method available:

android onrestoreinstancestate methods

The super method implementation restores the view hierarchy.

Generally, onRestoreInstanceState isn’t used to restore values often now. The same can be done from the Bundle in the onCreate method. Also since the onCreate method is always called before, it is a good practice to restore the saved instances there only.

In the following section, we’ll be creating a Counter Application in which we’ll save the state of the counter using the above methods.

Project Structure

android save restore instance project

Code

The code for the activity_main.xml is given below:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="16dp"
    android:orientation="vertical"
    tools:context=".MainActivity">


    <EditText
        android:id="@+id/inName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Username" />


    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Phone number"
        android:inputType="phone" />


    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="0"
        android:textSize="32sp" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="COUNT UP" />


</LinearLayout>

In the above layout, the second EditText doesn’t have any id set. So when the device is rotated or any configuration happens that causes the activity to recreate, this EditText contents would be reset.

The code for the MainActivity.java is given below:


package com.journaldev.androidsaverestoreinstance;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    Button button;
    TextView textView;
    int counter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (savedInstanceState != null) {
            String message = savedInstanceState.getString("message");
            Toast.makeText(this, message, Toast.LENGTH_LONG).show();

            counter = savedInstanceState.getInt("counter", 0);
        }

        button = findViewById(R.id.button);
        textView = findViewById(R.id.textView);
        textView.setText(String.valueOf(counter));


        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                counter = Integer.valueOf(textView.getText().toString()) + 1;
                textView.setText(String.valueOf(counter));
            }
        });
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString("message", "This is a saved message");
        outState.putInt("counter", counter);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        Toast.makeText(getApplicationContext(), "onRestoreInstanceState", Toast.LENGTH_SHORT).show();
        counter = savedInstanceState.getInt("counter", 0);

    }

}

In this the save the integer value of the counter and then when the activity is recreated, the onCreate gets called again. Over there we check if the savedInstanceState Bundle is null or not. If it isn’t we restore the views with the data from the counter.

The output of the application in action is given below:

android save restore instance state

Notice that the Phone Number field goes empty when the orientation was changed.

This brings an end to this tutorial. You can download the project from the link below.

Comments

  1. Rahul Nag says:

    The first edits text data has been saved although you have not used it inside the onSaveInstanceState and onRestoreInstanceState.
    is this due to that the first edit text has its id value but the second edit text don’t?

    1. sajal says:

      By default, Edittext save their own instance when changing orientation.

      Be sure that the 2 Edittexts have unique IDs and have the same IDs in both Layouts.

      That way, their state should be saved and you can let Android handle the orientation change.

      If you are using a fragment, be sure it has a unique ID also and you dont recreate it when recreating the Activity.

  2. lovely says:

    why dose the Phone Number field goes empty when the orientation was changed? please explain!!

Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages