Handling Android Activity State Changes in Android Studio

From Techotopia
Jump to: navigation, search
PreviousTable of ContentsNext
Understanding Android Application and Activity LifecyclesAndroid Activity State Changes - An Android Studio Example


You are currently reading the Android Studio 1.x - Android 5 Edition of this book.

Purchase the fully updated Android Studio 2.3 / Android 7 Edition of this publication in eBook ($19.99) or Print ($45.99) format

Android Studio 2.3 Development Essentials - Android 7 Edition Print and eBook (ePub/PDF/Kindle) editions contain 77 chapters and over 810 pages

Buy eBook Buy Print Preview Book


Based on the information outlined in the chapter entitled Understanding Android Application and Activity Lifecycles it is now evident that the activities that make up an application pass through a variety of different states during the course of the application’s lifespan. The change from one state to the other is imposed by the Android runtime system and is, therefore, largely beyond the control of the activity itself. That said, in most instances the runtime will provide the activity in question with a notification of the impending state change, thereby giving it time to react accordingly. In most cases, this will involve saving or restoring data relating to the state of the activity and its user interface.

The primary objective of this chapter is to provide a high-level overview of the ways in which an activity may be notified of a state change and to outline the areas where it is advisable to save or restore state information. Having covered this information, the chapter will then touch briefly on the subject of activity lifetimes.




The Activity Class

With few exceptions, activities in an application are created as subclasses of either the Android Activity class, or another class that is, itself, subclassed from the Activity class (for example the ActionBarActivity or FragmentActivity classes).

Consider, for example, the simple AndroidSample project created in Creating an Example Android App in Android Studio. Load this project in the Android Studio environment and locate the AndroidSampleActvity.java file (located in app -> java -> com.ebookfrenzy.androidsample). Having located the file, double click on it to load it into the editor where it should read as follows:

package com.ebookfrenzy.androidsample;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;

public class AndroidSampleActivity extends ActionBarActivity {

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

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.android_sample, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

}

When the project was created, we instructed Android Studio also to create an initial activity named AndroidSampleActivity. As is evident from the above code, the AndroidSampleActivity class extends, and is therefore a subclass of, the ActionBarActivity class.

A review of the reference documentation for the ActionBarActivity class would reveal that it is itself a subclass of the Activity class. This can be verified within the Android Studio editor using the Hierarchy tool window. With the AndroidSampleActivity.java file loaded into the editor, click on ActionBarActivity in the public class declaration line and press the Ctrl-H keyboard shortcut. The hierarchy tool window will subsequently appear displaying the class hierarchy for the selected class. As illustrated in Figure 11-1, ActionBarActivity is clearly subclassed from the FragmentActivity class which is itself a subclass of the Activity class:

The Android Studio Class Hierarchy window

Figure 11-1


This raises the question as to why ActionBarActivity was used instead of the Activity class. The reason for this can be traced back to the selections made when the project was first created. When choosing the SDK version targets for the project in the chapter entitled Creating an Example Android App in Android Studio, the project was configured to target a minimum SDK level of API 8: Android 2.2. Since the introduction of Android 3.0, however, applications have included an ActionBar view across the top of the screen which provides menu options and information to the user. The purpose of the ActionBarActivity class is to make this ActionBar available to applications that are required to run on older versions of Android and is included as part of the android.support.v7 support library. Had we specified API 11: Android 3.0 or later as the minimum SDK for the AndroidSample project, however, the activity would have been declared as a subclass of the Activity class instead of ActionBarActivity since backwards compatibility for the ActionBar would not have been required.

The Activity class and its subclasses contain a range of methods that are intended to be called by the Android runtime to notify an activity that its state is changing. For the purposes of this chapter, we will refer to these as the activity lifecycle methods. An activity class simply needs to override these methods and implement the necessary functionality within them in order to react accordingly to state changes.

One such method is named onCreate() and, turning once again to the above code fragment, we can see that this method has already been overridden and implemented for us in the AndroidSampleActivity class. In a later section we will explore in detail both onCreate() and the other relevant lifecycle methods of the Activity class.

Dynamic State vs. Persistent State

A key objective of Activity lifecycle management is ensuring that the state of the activity is saved and restored at appropriate times. When talking about state in this context we mean the data that is currently being held within the activity and the appearance of the user interface. The activity might, for example, maintain a data model in memory that needs to be saved to a database, content provider or file. Such state information, because it persists from one invocation of the application to another, is referred to as the persistent state.

You are currently reading the Android Studio 1.x - Android 5 Edition of this book.

Purchase the fully updated Android Studio 2.3 / Android 7 Edition of this publication in eBook ($19.99) or Print ($45.99) format

Android Studio 2.3 Development Essentials - Android 7 Edition Print and eBook (ePub/PDF/Kindle) editions contain 77 chapters and over 810 pages

Buy eBook Buy Print Preview Book

The appearance of the user interface (such as text entered into a text field but not yet committed to the application’s internal data model) is referred to as the dynamic state, since it is typically only retained during a single invocation of the application (and also referred to as user interface state or instance state).

Understanding the differences between these two states is important because both the ways they are saved, and the reasons for doing so, differ.

The purpose of saving the persistent state is to avoid the loss of data that may result from an activity being killed by the runtime system while in the background. The dynamic state, on the other hand, is saved and restored for reasons that are slightly more complex.

Consider, for the sake of an example, that an application contains an activity (which we will refer to as Activity A) containing a text field and some radio buttons. During the course of using the application, the user enters some text into the text field and makes a selection from the radio buttons. Before performing an action to save these changes, however, the user then switches to another activity causing Activity A to be pushed down the Activity Stack and placed into the background. After some time, the runtime system ascertains that memory is low and consequently kills Activity A to free up resources. As far as the user is concerned, however, Activity A was simply placed into the background and is ready to be moved to the foreground at any time. On returning Activity A to the foreground the user would, quite reasonably, expect the entered text and radio button selections to have been retained. In this scenario, however, a new instance of Activity A will have been created and, if the dynamic state was not saved and restored, the previous user input lost.

The main purpose of saving dynamic state, therefore, is to give the perception of seamless switching between foreground and background activities, regardless of the fact that activities may actually have been killed and restarted without the user’s knowledge.

The mechanisms for saving persistent and dynamic state will become clearer in the following sections of this chapter.


The Android Activity Lifecycle Methods

As previously explained, the Activity class contains a number of lifecycle methods which act as event handlers when the state of an Activity changes. The primary methods supported by the Android Activity class are as follows:

  • onCreate(Bundle savedInstanceState) – The method that is called when the activity is first created and the ideal location for most initialization tasks to be performed. The method is passed an argument in the form of a Bundle object that may contain dynamic state information (typically relating to the state of the user interface) from a prior invocation of the activity.
  • onRestart() – Called when the activity is about to restart after having previously been stopped by the runtime system.
  • onStart() – Always called immediately after the call to the onCreate() or onRestart() methods, this method indicates to the activity that it is about to become visible to the user. This call will be followed by a call to onResume() if the activity moves to the top of the activity stack, or onStop() in the event that it is pushed down the stack by another activity.
  • onResume() – Indicates that the activity is now at the top of the activity stack and is the activity with which the user is currently interacting.
  • onPause() – Indicates that a previous activity is about to become the foreground activity. This call will be followed by a call to either the onResume() or onStop() method depending on whether the activity moves back to the foreground or becomes invisible to the user. Steps should be taken within this method to store any persistent data required by the activity (such as data stored to a content provider, database or file). This method should also ensure that any CPU intensive tasks such as animation are stopped.
  • onStop() – The activity is now no longer visible to the user. The two possible scenarios that may follow this call are a call to onRestart() in the event that the activity moves to the foreground again, or onDestroy() if the activity is being terminated.
  • onDestroy() – The activity is about to be destroyed, either voluntarily because the activity has completed its tasks and has called the finish() method or because the runtime is terminating it either to release memory or due to a configuration change (such as the orientation of the device changing). It is important to note that a call will not always be made to onDestroy() when an activity is terminated.

In addition to the lifecycle methods outlined above, there are two methods intended specifically for saving and restoring the dynamic state of an activity:

  • onRestoreInstanceState(Bundle savedInstanceState) – This method is called immediately after a call to the onStart() method in the event that the activity is restarting from a previous invocation in which state was saved. As with onCreate(), this method is passed a Bundle object containing the previous state data. This method is typically used in situations where it makes more sense to restore a previous state after the initialization of the activity has been performed in onCreate() and onStart().
  • onSaveInstanceState(Bundle outState) – Called before an activity is destroyed so that the current dynamic state (usually relating to the user interface) can be saved. The method is passed the Bundle object into which the state should be saved and which is subsequently passed through to the onCreate() and onRestoreInstanceState() methods when the activity is restarted. Note that this method is only called in situations where the runtime ascertains that dynamic state needs to be saved.

When overriding the above methods in an activity, it is important to remember that with the exception of onRestoreInstanceState() and onSaveInstanceState(), the method implementation must include a call to the corresponding method in the Activity super class. For example, the following method overrides the onRestart() method but also includes a call to the super class instance of the method:

protected void onRestart() {
	super.onRestart();
	Log.i(TAG, "onRestart");
}

Failure to make this super class call in method overrides will result in the runtime throwing an exception during execution of the activity. Whilst calls to the super class in the onRestoreInstanceState() and onSaveInstanceState() are optional there are considerable benefits in doing so, a subject that will be covered in the chapter entitled Saving and Restoring the User Interface State of an Android Activity.

Activity Lifetimes

The final topic to be covered involves an outline of the entire, visible and foreground lifetimes through which an activity will transition during execution:

  • Entire Lifetime – The term “entire lifetime” is used to describe everything that takes place within an activity between the initial call to the onCreate() method and the call to onDestroy() prior to the activity terminating.
  • Visible Lifetime – Covers the periods of execution of an activity between the call to onStart() and onStop(). During this period the activity is visible to the user though may not be the activity with which the user is currently interacting.
  • Foreground Lifetime – Refers to the periods of execution between calls to the onResume()and onPause() methods.

It is important to note that an activity may pass through the foreground and visible lifetimes multiple times during the course of the entire lifetime.

The concepts of lifetimes and lifecycle methods are illustrated in Figure 11-2:


The Android lifetime and lifecycle diagram

Figure 11-2

Summary

All activities are derived from the Android Activity class which, in turn, contains a number of event methods that are designed to be called by the runtime system when the state of an activity changes. By overriding these methods, an activity can respond to state changes and, where necessary, take steps to save and restore the current state of both the activity and the application. Activity state can be thought of as taking two forms. The persistent state refers to data that needs to be stored between application invocations (for example to a file or database). Dynamic state, on the other hand, relates instead to the current appearance of the user interface.

In this chapter, we have highlighted the lifecycle methods available to activities and covered the concept of activity lifetimes. In the next chapter, entitled Android Activity State Changes – An Example Application, we will implement an example application that puts much of this theory into practice.


You are currently reading the Android Studio 1.x - Android 5 Edition of this book.

Purchase the fully updated Android Studio 2.3 / Android 7 Edition of this publication in eBook ($19.99) or Print ($45.99) format

Android Studio 2.3 Development Essentials - Android 7 Edition Print and eBook (ePub/PDF/Kindle) editions contain 77 chapters and over 810 pages

Buy eBook Buy Print Preview Book



PreviousTable of ContentsNext
Understanding Android Application and Activity LifecyclesAndroid Activity State Changes - An Android Studio Example