Apps can be tricky to handle from a programming perspective because they always exist in tandem with other apps and programs. This is normal for computers and other larger devices, but the limited memory and processing power of mobile devices, particularly smartphones, means that apps have to be carefully constructed with a lifecycle. The lifecycle has to appeal to how a user wants to make use of the app, while also subtly preventing them from closing it entirely, or deleting it, because it hogs all their processing speed.
In general, the activity lifecycle of an app has three steps – starting an activity, pausing and resuming an activity, and stopping and restarting an activity. This article is an overview of how each of those steps can be handled, and also discusses the topic of how apps are restarted after they have been closed. Each topic includes advice about how to guide customers through the process of starting/restarting, and offers tips to manage memory to the best of your ability, while also getting customers the most use out of your app that they can.
Understanding the activity lifecycle
The phases of an app lifecycle can be organized into a sort of stepped pyramid. Each stage in the activity lifestyle is a step in the pyramid, and the app can ascend or descend the steps. The top “step” is when the app is visible to users and being used for its particular function. This image is a simple visual aid for understanding the three different activity states mentioned previously.
As you can see, the lifecycle starts at the bottom left with the onCreate() command, tiers up to created, started, and resumed states, and then tiers down to the paused, stopped, and finally, destroyed states. Notably, the app can be restored through any of the paused or stopped states, but once it is destroyed, it must be recreated, which we will talk about later in the last section of this article.
As the diagram suggests, starting an app actually begins when the app is created. This is when the app is installed, meaning when it starts using memory on the device it’s installed on. After an app is created, it can be started, which creates a new active instance of the app. This categorizes memory objects and loads the app to its most active state, which is the top tier, resumed. Also referred to as the running state, the resumed state is active when the user has the app in the foreground and is able to interact with it. This is different from the started state because the started state does not offer the app’s full functionality – think of it as a loading screen or something similar. There are a lot of ways that you can specify launch instructions for an app, such as launching in multiple instances or defining which activity the AndroidManifest.xml file sees as the root of the project.
An app is paused when its foreground activity is obstructed by other visual components or other activity that causes it to briefly stop its functionality but not halt entirely. The important distinction here is that the activity is partially visible, but not in focus – and when focus does return to it, then it resumes its activity. When it becomes fully obstructed, then it is stopped, which we will talk about later.
Although it is entirely possible that a user will return focus to your app after it has been paused, this is usually the first sign that a user is finished with the app and will be closing it soon. To that end, calling an onPause() command means that you should use it to stop animations or other ongoing activities that can use up processing power, commit unsaved changes (but only if the user expects changes to be saved, such as in an email draft), and release system resources like broadcast receives, handles to sensors (like a camera or GPS), or any resource that might affect battery life.
Bear in mind that, while you want these shutdown features, loading too many of them into an onPause() feature can slow down the transition to the next activity, and the heaviest stop options should occur on during an onStop() command rather than onPause(). When an activity is resumed, basically all of the features that have shut down need to be restored. This is another reason to make the pause load fairly light – a lot of apps mismanage these, causing them to run slowly and loose customer interest as a result.
Stopping an app doesn’t actually halt it entirely – apps work by always remaining active in some sense because it makes them a lot faster. Stopping an app occurs, as mentioned previously, when all of its UI features are obscured, and only an icon remains, which can later be used to recreate it. The onStop() and onRestart() lifecycle methods are basically larger versions of the onPause() and onResume() commands that I described a moment ago. It is best used when a user’s focus has left your app entirely and has gone to another activity or to another app. The onStop() command releases all resources like external hooks or active forms and puts the app in a holding pattern with basically only the ability to turn back on again. It is important to note that this allows data storage to be persistent throughout multiple stops and starts to the app, because its memory objects are still intact throughout the stopped state and throughout other restart, pause, or resume actions.
Recreating an app is a slightly different task than what we’ve been talking about so far. When an app is destroyed, its process is halted entirely. This is different from the stop command above because it no longer accesses memory at all. This doesn’t mean that it is deleted from the device, just that it can’t use any memory until another instance of the program is created with the onCreate() command. This image is a visual of the relationship between several of these states:
Data from the app can be saved outside of a destroyed state, but it must use an external archive through the phone’s physical memory. Typically, this is uncommonly done, but it can happen in certain situations. Recreating an app after it has been destroyed is very similar to the process for creating an app in the first place. However, it also must access these external archives and link them to an activity state, which then restores the app to whatever state it was in when it was destroyed.
There you have the basics to managing the activity lifecycle of your Android app.