Previous  | Next  | Home

Application Lifecycles


 

A title like "Application Lifecycles" might tempt you to hurry on to a more interesting section. That would be a mistake. 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. Your app may "sort of work" if you write it without attention to lifecycles, but it may not offer the best user experience and may be a poor citizen in the app ecosystem because it may consume resources unnecessarily.

 

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 method
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

The last column indicates the likely next action that will be invoked in the lifecycle and 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 Activity 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 operates like a true multitasking operating system, as we discussed in the Introduction. Thus, when your app is removed from the foreground its onPause() method is invoked and possibly its onStop() method (both by the operating system), 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), or often most efficiently by using the Multitasking Button described in the following box.


Android phones and tablets facilitate multitasking by making it easy to find the applications that have most recently been executing in the foreground. Since Android 4.0, this functionality has been accessed in stock Android by clicking the multitasking button (the lower right button that looks like a rectangle or two overlapping rectangles in the image below), which brings up the scrollable multitasking window displaying the most-recently used applications, as illustrated in the following figure.




(For older devices this window is accessed by different means, for example a long-press on the HOME key.) Clicking on one of the displayed icons will bring the resulting app back to the foreground, usually sufficiently quickly that the user perceives the app to have been running all the time in the background (even though it probably hasn't).

This multitasking environment with effortless task switching and efficient use of device resources is one of the most powerful features of Android. Taking full advantage of it in your applications requires a basic understanding of how the lifecycle of an app functions.


In the above figure, only MapExample is currently in the foreground. Most of the other apps in the list (there are many others not shown) are apps that have been in the foreground in the past few days. This app will be developed in the project Map Example. It is currently in the background, which means that it can be relaunched quickly from the multitasking window, but also means that it could be consuming system resources if they were not released when the app was sent to the background. Mapping Demo 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.

 

But Multitasking Requires that the Programmer Understand Lifecycles

The multitasking capability described above is part of what makes Android devices quite nimble, with apps often appearing to load and initialize very quickly. 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 is not as complicated as it might sound because the multitasking resource management is largely handled by Android under the hood, 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 figure below left shows some of the applications running on a Samsung Galaxy Nexus phone. (This example is from the early days of Android, with the device running Android 2.2.) The applications displayed here correspond both to apps and to services, and if one scrolls a total of 24 tasks and/or services are listed as running. The right figure shows the power consumption by various tasks after the phone was unplugged from the power source for 30 minutes (with nothing done about the apps still running in the background).



Clearly "all those background apps" are not using significant power. As the right figure shows, the power is being consumed by the usual culprits: the display, the networking, the phone operating system, the cell phone, ... The only background application from the figure displayed on the left using 5% or more of the power is the K-9 email app, and that presumably is mostly because it is running a service that is receiving push email and checking servers for email.


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.

Begininning with Android 6 (API 23) the Android OS has become even more aggressive at reducing power consumed by apps through the Doze and App Standby projects. These new power-saving features manage how apps behave when a device is on battery power. Doze defers background CPU and network activity for apps when the device is not used for long periods of time. App Standby defers background network activity for apps that the user hasn't interacted with recently. I presently (2016) have a Nexus 6P running Android 6.0.1 and can state from experience that these new technologies reduce the already low battery consumption for apps in the background to almost zero if the phone is not being used or moved.

 

Multitasking and Resources

Excellent discussions 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 original iPhone and iPad approach, before Apple adopted many of Android's approaches to multitasking) 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.


Particularly in the early days of Android, one could find considerable lore on the internet that "task killer" apps are important utilities for Android devices because the battery life can be extended and the performance of the phone enhanced by manually killing apps that are not currently being used. This is a misconception, like much lore on the internet, fueled by the experience of some early users with a few poorly-written apps running on phones with relatively small amounts of memory, by failure to appreciate that some quite marvelous smartphone hardware devices consume a lot of power when they are used, by failure to understand the Android multitasking model, and by no small amount of deliberate obfuscation by fans of certain other multitasking-challenged smartphones and tablets.

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 I recommend which conclude that task killers generally do more harm than good when they are used to selectively kill tasks on an Android phone.

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 that consumes significant power, like a GPS location-tracking app), not that the Android operating system is a particularly voracious consumer of power. It is unusual for a modern app installed from reputable sources to go rogue, but it can happen. Then it may be useful to stop the app, delete its cache, and see if that fixes the problem (and uninstall and notify the author it if it doesn't). But even that does not require a separate task killer app, since as of version 4.0 (Ice Cream Sandwich) Android has built in the capability to monitor tasks and kill them manually in the unlikely event that it becomes necessary. A concise introduction to this functionality may be found in How to Manage Running Apps on Android.

Of course, if an app on any smartphone is in the foreground and using power-hungry devices, 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, and is no justification for a task killer app, particularly because Android has its own quite-lethal automatic task killer, as we now discuss.

 

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 hands-on technical detail how the lifecycle methods operate in the Android multitasking environment.

Last modified: July 25, 2016


Previous  | Next  | Home