Previous  | Next  | Home

Application Lifecycles


 

A title like "Application Lifecycles" may tempt you to skip to the next more interesting section. That would be a mistake in this case. It is very important to have a basic understanding of the lifecycle for an activity in Android in order to efficiently manage resources on limited devices, and to ensure a seamless response for the user.

 

Overview of Android Lifecycles

A general overview of the lifecycle of an application is shown in the following figure, which is taken from the documentation for Activity.

Notice in particular that when another activity comes to the foreground it does not generally mean that the task originally in the foreground (your app, say) is discarded. The seven methods contained in square boxes in the preceding diagram are called the lifecyle methods because they govern the lifecycles of Android applications. Their properties are summarized in the following table.


Activity Lifecycle Methods
Method Description Killable Next
onCreate() Called when activity first created No onStart()
onRestart() Called after activity stopped, prior to restarting No onStart()
onStart() Called when activity is becoming visible to user No onResume()/onStop()
onResume() Called when activity starts interacting with user No onPause()
onPause() Called when a previous activity is about to resume Yes onResume()/onStop()
onStop() Called when activity no longer visible to user Yes onRestart()/onDestroy()
onDestroy() Final call received before activity is destroyed Yes Nothing

We shall explain the "Killable" column further below.

 

The Three Lives of Android

It is useful to think of an application in Android having three "lifetimes" associated with the preceding diagram and table (see the documentation of Activities for a more thorough discussion).

  1. The Entire Lifetime: the period between the first call to onCreate() to a single final call to onDestroy(). We may think of this as the time between setting up the initial global state for the app in onCreate() and the release of all resources associated with the app in onDestroy().

  2. The Visible Lifetime: The period between a call to onStart() until a corresponding call to onStop(). Although this is termed the "visible lifetime", the app may not be directly visible and interacting with the user at any one time if it is not in the foreground. The feature that distinguishes this lifetime is that, even if not in the foreground, the app maintains resources such that it can instantaneously return to the foreground.

  3. The Foreground Lifetime: The period between a call to onResume() until a corresponding call to onPause(). During foreground lifetime the activity is in front of all other activities and interacting with the user.

Notice from these definitions that in general more than one app may be in its visible lifetime at a particular time, though only one of these apps will be in the foreground and literally visible and interacting with the user at any one time.


Because multiple apps may be in their "visible lifetime" at a given time, we may expect that their corresponding onResume() and onPause() methods could be invoked often if they are moved in and out of the foreground by user actions (for example, a user jumping among a calendar, a weather app, a news app, texting, a contacts list, an incoming phone call, and so on). Thus we should endeavor to keep the code in these methods as lightweight as possible.

 

True Multitasking

Android is a true multitasking operating system (unlike the iPhone, which in its original form did not allow ordinary developers access to multitasking and even in the new iPhone 4 permits only a limited form of multitasking). Thus, when your app is removed from the foreground its onPause() method is invoked and possibly its onStop() method, but if Android decides that it has sufficient resources it will maintain the app in a background state that can be brought quickly back to the foreground (for example, by clicking on the app's icon, or clicking the Back button---the curved back arrow---on the device).


Many phones facilitate multitasking by making it easy to find the applications that have most recently been executing in the foreground. For example, on both the Motorola Backflip and Samsung Captivate phones a long-press on the HOME key brings up a window displaying the icons of the most-recently used applications, as illustrated in the following figure.



Clicking on one of the displayed icons will immediately bring the resulting app back to the foreground.

But Multitasking Has a Price

This multitasking capability is part of what makes Android devices quite nimble, with apps often appearing to load and initialize much faster than for the iPhone. However, as with all good things there is a price: the developer must remember that just because you execute a finish() command in your app does not mean that it is no longer running. It is very likely still in the background in a paused or stopped state if the device is not overtaxed for resources. This means that as a programmer you have to be careful that an app not in the foreground is not consuming valuable system resources to no useful end. For example, various features of the device like the GPS or cameras can consume power rapidly, so a poorly written app can lead to very short battery life for the device, and an unhappy user.

This multitasking resource management is largely handled by Android as long as you tell it to do so. We shall see various examples of managing resources when apps move between foreground and background and vice-versa, but the most essential point is that (from the above diagram) we expect that an app executes onPause() when leaving the foreground and onResume() when coming to the foreground. Thus, the programmer should release un-needed resources (like requests for periodic updates from location services, which invoke the power-hungry GPS radio) in onPause() and restore them in onResume().

 

Examples from Android Devices

It is instructive to illustrate the preceding comments by examining the applications running on a real device. The program Advanced Task Killer (there is a free version, with ads, that we will use for illustration) available from the Android Market is a useful tool because it shows all apps running on a device (and permits you to kill selectively individual apps, but here we just want to use it to examine what is running on a device). The following figure shows some of the applications running on a Motorola Backflip Android phone.



In this example, only Advanced Task Killer is currently in the foreground. Most of the other apps appearing in this part of the list (there are others not shown) are apps that have been in the foreground in the past few days. For example, the app Mapping Demo is a user-written app that was running and has been terminated recently by clicking its Exit button (which releases some resources and executes finish()). Although it is not in the foreground, we see that it is currently running in the background, which means that it can be relaunched quickly, but also means that it could be consuming system resources if they were not released when the app was sent to the background. This app has the capability to use location services to track the position of the device. Later, we will see exactly what the app Mapping Demo does in its onPause() and onResume() (and other) methods to manage its location services so that the GPS only runs when it is needed.


The preceding example illustrates clearly that merely terminating the app will not generally cause it to disappear. If the operating system judges that it has ample resources available, it will likely send the app to the background rather than removing it completely at that point, and it may continue to keep parts of the app around in background (for weeks) if the system does not get taxed for resources or is not rebooted. Indeed, at the top of the above figure we see that when this screen shot was taken the phone had 46M of memory available, so it is not hurting for memory in letting all of those apps continue to run in the background (there could be other reasons to kill the app, but certainly available memory would be one key criterion).

The following figures illustrates for another Android device, a Samsung Galaxy S phone, that "all those background apps" are not consuming significant power. The left figure shows a partial list of all the apps "running" on the phone (with 68M free). The right figure shows the power consumption after the phone was unplugged from the power source for 30 minutes and not used (with the apps still running in the background).



As the right figure shows, the power is being consumed by all the usual culprits: the display, the networking, the phone operating system, cell phone standby, ... None of the background applications even shows up in the list, indicating that they are at the 1 percent level or less in power consumption.


A closely-related issue is addressed in When to Include an Exit Button in Android Apps. This article argues convincingly that what users want with an Exit button is an assurance that the app will no longer consume resources after the button is pressed, but this is exactly what hitting the Back button does in a correctly written app (see the demonstration of this in the project Lifecycle Methods). Thus an Exit button is actually rather superfluous in an Android application because it duplicates the action of the Back button that already exists on the phone.

 

Multitasking and Resources

An excellent discussion of the sophisticated relationship between processes and applications in Android, and the manner in which Android implements a multitasking experience on a limited device (and the contrast with the iPhone approach) may be found in the following links.

As these discussions illustrate clearly, just because old applications appear in a list of "running apps" does not mean at all that those apps are either slowing the phone or draining the battery.


Some lore is about on the internet that programs like Advanced Task Killer are important utilities for Android devices because the battery life can be extended by manually killing apps that are not currently being used. This is almost certainly a misconception---like much lore on the internet---fueled by the experience of some users with a few poorly written apps, by failure to appreciate that some quite marvelous devices on phones consume a lot of power when they are used, and some deliberate obfuscations by fans of certain multitasking-challenged smartphones. Android is built on a Linux kernel, which should be quite adept at managing its own resources---when is the last time that you worried that a Unix workstation needed your intervention in such matters? For further discussion of these issues I recommend all of which conclude that task killers generally do more harm than good when they are used to selectively kill tasks on an Android phone.

I use both an iPhone and an Android (a Motorola Backflip). Both have long battery life if you use them for only a few things; both consume battery quickly if you use then extensively for talking, surfing the web, location services, ... As we shall show in later examples, if an Android app not in the foreground is consuming significant power it is likely that it is incorrectly written (unless it is being run deliberately as a service), not that the Android operating system is a particularly voracious consumer of power.

Of course, if an app on any smartphone is in the foreground and using power-hungry devices on the phone, battery life will be comparatively short. But that is primarily because of the laws of physics and the present status of battery technology, not the relative merits of computer operating systems.

 

Android Is a Stone Cold Killer

Of particular importance for the Android programmer is the column marked "Killable" in the preceding table of lifecycle methods. As discussed above, Android implements multitasking on limited devices that may not have the hardware capability for normal multitasking. In such an environment, a major danger is that a device can suddenly be taxed for memory and fail catastrophically because of an out-of-memory exception if it cannot remedy this situation quickly. Android deals with this by reserving the option to kill processes brutally and without warning---not allowing those processes to execute another line of code---thus allowing the kernel to quickly reclaim the freed resources. (See the particularly clear discussion of these issues by Dianne Hackborn in Multitasking the Android Way.)

An Android programmer must write applications with the expectation that they could be killed at any time by the operating system. But Android does not kill processes unless it needs the resources, and it does not kill processes randomly when it decides it must reclaim resources. In choosing which processes to kill mercilessly in a low-memory situation, Android uses an algorithm that takes into account both the importance of a process for the user's current experience and how long it has been since the user has needed the process. This is where the Killable column in the lifecycle processes table comes into play.

Generally, if the Killable column is marked "Yes" for a method, after that method returns the process hosting the activity may be killed by the system at any time and without warning. Thus, any data that need to persist to allow for a rapid restart of the app if it is killed must be saved during a portion of the lifecycle when it is not subject to sudden extermination. From the preceding figure and table, we see that the logical place to do this is in the onPause() method, which is executed when an app is being sent to the background, since onPause() should complete but there is no guarantee that the onStop() and especially the onDestroy() methods will be executed at all if Android kills the app suddenly while it is in the background in a low-memory situation.

In the project Lifecycle Methods we shall explore in considerable technical detail how the lifecycle methods operate in the Android multitasking environment.


Previous  | Next  | Home