Overview

Android app development is made to provide smart computing with less amount of power and memory resources. In order to achieve multitasking in low memory resources, Android smartly manages process lifecycles.

To maintain the integrity of the runtime data members during the lifecycle of an app, it is necessary to understand the concept of saving and restoring states.

States in Android

In Android app development, every Android app can have any of the following states at any instance of time:

  1. Created
  2. Started
  3. Resumed
  4. Paused
  5. Stopped
  6. Destroyed

Of course, every one of us knows lifecycle methods attached to them.

 

Lifecycle of An Activity

 

When an Activity or Fragment gets destroyed, every data member values and values attached to views are cleared. So, every data member and views will be initialized again if the Activity or Fragment is created again.

Scenarios when the Activity is destroyed

  1. User closes the activity using back press.
  2. Programmatically calling finish() method of activity.
  3. The system tries to recover memory if the activity is in the Stopped state and hasn’t been used in a long time, or if the foreground activity requires more resources.
  4. Configuration changes like Screen Rotation, Language change, Font size change etc.

Android is smart enough to detect if the activity is destroyed by user action or if the activity is destroyed due to some system constraint.

When activity is destroyed by system constraints as mentioned in point 3 and 4 above, the system knows that activity previously existed and when the user navigates back to it, it creates the activity with the use of data which was saved at the time it was destroyed.

Android saves this type of data in Bundle instance.

Saving Instance States

For mobile app development, in order to retain the data after the activity gets destroyed, we need to save the data members of our activity in the Bundle instance which Android will use to create the activity next time.

For that, we can use onSaveInstanceState() method.

The superclass implementation of onSaveInstanceState() has a great feature in-built: it saves the transient data of views such as text in EditText, TextView or scroll position of RecyclerView at the time when activity is being stopped.

So when the activity is re-created, the views restore their values automatically. This feature will only work for the views which have the IDs assigned.

To save instance variable values of the activity, you can override the method like this:

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // Always call the superclass so it can save the view hierarchy state
    super.onSaveInstanceState(savedInstanceState);
    // Save the user's current game score
    savedInstanceState.putInt(SCORE_COUNT, mCurrentScore);
}

You can save any type of primitive data as well as any complex instance which implement Serializable or Parcelable in the Bundle provided by onSaveInstanceState() method.

onSaveInstanceState() is executed after onPause() and before onStop().

Restoring Instance States

There are two ways of restoring the states:

  1. Restoring states from onCreate() method.
  2. Restoring states from onRestoreInstanceState() method.

You may have noticed that onCreate() method has a parameter of type Bundle. This bundle instance is null when the activity is opened for the first time. But when the activity is recreated, the bundle instance contains the values saved at the time of calling onSaveInstanceState().

To restore states from onCreate() method, you need to override the onCreate() method like this:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState); // Always call the superclass to restore view states
    // Check whether we're recreating a previously destroyed instance
    if (savedInstanceState != null) {
        // Restore value of members from saved state
        mCurrentScore = savedInstanceState.getInt(SCORE_COUNT);
    } else {
        // initialize members with default values for a new instance
    }
    ...
}

To restore states from onRestoreInstanceState() method, you need to override the onRestoreInstanceState() method like this:

public void onRestoreInstanceState(Bundle savedInstanceState) {
    // Always call the superclass so it can restore the view hierarchy
    super.onRestoreInstanceState(savedInstanceState);
    // Restore state members from saved instance
    mCurrentScore = savedInstanceState.getInt(CURRENT_SCORE);
}

This method is executed only when data is saved in the Bundle. So, when the activity is opened for the first time, this method is not called.

onRestoreInstanceState() is executed after the onStart() method of the activity.

You can choose the way of restoring the data based on your needs.

Advantages of using lifecycle methods to Save and Restore instance states

Consider you have an activity which calls an API to show the list of data in RecyclerView. You call the API from onCreate() to retrieve the list.

After the list is fetched, just rotate your phone. You will be able to see that the API is called again, which is not we want as the data was already loaded and it should not be reloaded unless the user wants to.

To handle this scenario, you can simply save your list in onSaveInstanceState() and restore it instead of loading it from the API by onCreate() with the Bundle.

Disadvantages of using lifecycle methods to Save and Restore instance states

The data you store during onSaveInstanceState() method is not persisted. It means you cannot restore the data after the app is closed by the user. If you wish to restore the data even after the app is closed, you need to use other approaches like SharedPreference, SQLite, etc.

It becomes complex if you have a large number of states to maintain during the lifecycle of the activity. For maintaining complex data structures, you can use ViewModel concept (which is now also an Architecture Component Provided by Google). ViewModels are scoped through the life of the activity and are not destroyed when in the case when activity will be recreated.

If you try to save larger data like Bitmap or Files into the Bundle, you’ll see the downgrade of the performance in your app.

For better understanding, you can refer the demo app on GitHub – https://github.com/LNAndroid/SavingStatesDemo

To know more or for a discussion please follow @letsnurture on Twitter. We will be happy to talk to you!

Happy Coding!! 🙂

 

Want to work with us? We're hiring!