Sunday, July 11, 2010

Lifecycle of an Android Application


In most cases, every Android application runs in its own Linux process. This process is created for the application when some of its code needs to be run, and will remain running until it is no longer needed and the system needs to reclaim its memory for use by other applications.

An important and unusual feature of Android is that an application process's lifetime is not directly controlled by the application itself. Instead, it is determined by the system through a combination of the parts of the application that the system knows are running, how important these things are to the user, and how much overall memory is available in the system.

It is important that application developers understand how different application components (in particular Activity, Service, and IntentReceiver) impact the lifetime of the application's process. Not using these components correctly can result in the system killing the application's process while it is doing important work.

A common example of a process lifecycle bug is an IntentReceiver that starts a thread when it receives an Intent in its onReceiveIntent() method, and then returns from the function. Once it returns, the system considers that IntentReceiver to be no longer active, and thus its hosting process no longer needed (unless other application components are active in it). Thus, it may kill the process at any time to reclaim memory, terminating the spawned thread that is running in it. The solution to this problem is to start a Service from the IntentReceiver, so the system knows that there is still active work being done in the process.

To determine which processes should be killed when low on memory, Android places them into an "importance hierarchy" based on the components running in them and the state of those components. These are, in order of importance:

   1. A foreground process is one holding an Activity at the top of the screen that the user is interacting with (its onResume() method has been called) or an IntentReceiver that is currently running (its onReceiveIntent() method is executing). There will only ever be a few such processes in the system, and these will only be killed as a last resort if memory is so low that not even these processes can continue to run. Generally at this point the device has reached a memory paging state, so this action is required in order to keep the user interface responsive.

   2. A visible process is one holding an Activity that is visible to the user on-screen but not in the foreground (its onPause() method has been called). This may occur, for example, if the foreground activity has been displayed with a dialog appearance that allows the previous activity to be seen behind it. Such a process is considered extremely important and will not be killed unless doing so is required to keep all foreground processes running.

   3. A service process is one holding a Service that has been started with the startService() method. Though these processes are not directly visible to the user, they are generally doing things that the user cares about (such as background mp3 playback or background network data upload or download), so the system will always keep such processes running unless there is not enough memory to retain all foreground and visible process.

   4. A background process is one holding an Activity that is not currently visible to the user (its onStop() method has been called). These processes have no direct impact on the user experience. Provided they implement their activity lifecycle correctly (see Activity for more details), the system can kill such processes at any time to reclaim memory for one of the three previous processes types. Usually there are many of these processes running, so they are kept in an LRU list to ensure the process that was most recently seen by the user is the last to be killed when running low on memory.

   5.An empty process is one that doesn't hold any active application components. The only reason to keep such a process around is as a cache to improve startup time the next time a component of its application needs to run. As such, the system will often kill these processes in order to balance overall system resources between these empty cached processes and the underlying kernel caches.

When deciding how to classify a process, the system picks the most important level of all the components currently active in the process. See the Activity, Service, and IntentReceiver documentation for more detail on how each of these components contribute to the overall lifecycle of a process. The documentation for each of these classes describes in more detail how they impact the overall lifecycle of their application.

No comments:

Post a Comment