Today we are going to discuss, how to handle an activity or fragment’s state changes using onSaveInstanceState. So after you complete this lesson, you will be able to handle such State change for Activities. Although, if you want to handle your fragment state, you can follow the same as discussed in this blog. However, at the end of this blog, you will have a video tutorial. You could watch that.

onSaveInstanceState
Figure 1.1 – Example of a configuration change

In every Android system, there are a number of events that can trigger a configuration change. And the most prominent example is a change between portrait and landscape orientations when a configuration change occurs, the activity is destroyed and recreated. In such cases the original activity instance will have onPause(), onStop(), and onDestroy() callbacks triggered. And when a new activity instance will be created, it will have onCreate(), onStart(), and onResume() callbacks triggered. If you dig deeper into your activity lifecycle you will find other two methods – onSaveInstanceState and onRestoreInstanceState can be called but only if any configuration change happens. See Figure 1.2

Suppose an activity is in the foreground, and the user taps the Back button, the activity transitions through the onPause(), onStop(), and onDestroy() but onSaveInstanceState  and onRestoreInstanceState will not. Because the user intentionally pressed that button.



Activity Lifecycle about configuration changes

According to the below diagram onSaveInstanceState will be called before/after the onStop method and onRestoreInstanceState will be called in between onStart and on onResume. Therefore, we can save our UI data before the onDestroy using onSaveInstanceState and retrieve data from the onCreate method by using savedInstanceState bundle variable or we could just override onRestoreInstanceState method in our activity or fragment.

onSaveInstanceState
Figure 1.2 – Activity lifecycle while saving and restoring data

Remember

  • onSaveInstanceState – used to save data in a bundle called outstate.
  • onRestoreInstanceState – used to recover that data from savedInstanceState bundle.



Let’s Handle the configuration changes

In this example, we will handle one of the common configuration change such as screen rotation. As we can see In the below graphics there we have a button and a text view. The button will be incrementing a counter value and that value will be updated in the text view even if there have any configuration change happened.

activity-state-chage
Figure 1.3 – Example of a configuration change

Store data on configuration change

If you noticed, whenever the device is rotating counter value changed to ZERO and that’s why text view is also changed to ZERO. Alright, to save that state we will override onSaveInstanceState and store the counter value in an outState variable like below code snippets.

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putInt("key_counter", counter);
}

Note: outstate is a bundle which requires key and value pair as it takes in onSaveInstanceState’s parameter.


Restore data on configuration change

Now when we have data in outState, we can easily retrieve that data to restore the UI by simply overriding onRestoreInstanceState or get the data from onCreate method savedInstanceState.

  • Retrieving data from onRestoreInstanceState
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    counter = savedInstanceState.getInt("key_counter", 0);
    txtTotal.setText("" + counter);
}

  • Retrieving data from onCreate
    private int counter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
      
        counter = 0;
       if (savedInstanceState != null) {
            counter = savedInstanceState.getInt("key_counter", 0);
        } else {
            counter = 0;
        }
    }

Inside onRestoreInstanceState and onCreate method parameter we also have a bundle object called savedInstanceState. And that bundle is actually holding all the outstate bundle’s data. Therefore the above two code snippets are just the two different places for retrieving data from the outState bundle.

Remember: when you are retrieving data from onCreate method you must have to check savedInstanceState != null otherwise you would have NullPointerException.

That’s it.


Test our Code

Now we have handled such configuration change in our app.

onSaveInstanceState
Figure 1.4 – OUTPUT: After Handling Activity State Changes

And that’s it for today. Next Shared Preferences.



Resources

Grab this complete MainActivity.java code

MainActivity.java

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "DailyCoding";
    private TextView txtTotal;
    private Button btnIncrement;

    private int counter;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        txtTotal = findViewById(R.id.txt_total);
        btnIncrement = findViewById(R.id.btn_increment);

        counter = 0;

       /* if (savedInstanceState != null) {
            counter = savedInstanceState.getInt("key_counter", 0);
        } else {
            counter = 0;
        }*/

        txtTotal.setText("" + counter);

        btnIncrement.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                counter++;
                txtTotal.setText("" + counter);
            }
        });

    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("key_counter", counter);
    }

    @Override
    protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        counter = savedInstanceState.getInt("key_counter", 0);
        txtTotal.setText("" + counter);
    }
}


activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:padding="10dp"
    android:gravity="center">

    <TextView
        android:id="@+id/txt_total"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="0"
        android:textSize="80sp"/>

    <Button
        android:id="@+id/btn_increment"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Increment Value"
        android:layout_below="@id/txt_total"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="10dp"
        android:textAllCaps="false"
        android:textSize="16sp"/>

</RelativeLayout>


Video Tutorial

Handle Activity State on Configuration changes

Complete Practical


Download this project to your local.


5 Comments

CBD oil for sale · February 13, 2021 at 8:06 pm

It’s perfect time to make a few plans for the longer term and it’s time to be happy.
I’ve learn this post and if I could I want to suggest you some attention-grabbing things or advice.
Perhaps you could write next articles relating to this article.
I want to learn even more issues approximately it!

    Subhojit · March 2, 2021 at 10:14 pm

    Yes, Sure!

Shared Preferences for Android App Development - Daily Coding · May 19, 2020 at 7:29 am

[…] Android, there are many different ways of storing data persistently (such as SavedInstanceState, SQLite or Cloud Firestore) for our applications. And Shared Preferences is one of them to store […]

What is an Android Activity | Complete Guide | Daily Coding · December 8, 2020 at 12:49 am

[…] at the beginning when all the views or activity is created. It also has a bundle object called savedInstanceState to get the previous state of the […]

Android Activity Lifecycle - with Use Cases | Daily Coding · December 16, 2020 at 10:54 pm

[…] will be called when all the views or activities are created. It also has a bundle object called savedInstanceState to get the previous state of the […]

Leave a Reply

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