Knowing how the Activity back stack works will help you to better understand how your activities are managed in the background. As the name implies, the Activity back stack organizes your Activities in a linear stack structure, based on the order in which each is started. Imagine we have an app used for scrolling through and viewing text messages. Each time you tap on a message in the list, a new Activity for reading the full contents of the text is instantiated. Doing this puts our new “message viewing” Activity on top of the stack. Pressing the back button will remove (pop) the Activity from the stack, destroying it in the process, and present the user with the previous list Activity. Activities in the stack are only ever pushed and popped, never rearranged.
This is the basic gist of the Activity back stack. When the user starts a new Activity, it is pushed on to the top of the stack and resumed (onResume). The previous Activity is stopped (onStop). Once the back button is pressed, it is popped off, returning the user to the previous Activity. A basic diagram showing how the stack looks before and after can be seen below
What about tasks?
There is also the concept of a task, which is basically a collection of activities committed to one app (or job). These activities are then organized in the back stack. The encapsulation can be seen as follows :
Task –> Back stack –> Activities
(a task contains Activities which are stored in the back stack)
Launch Modes & Intent Flags
Not all Activities behave the same way when they are launched. By default, a newly started Activity is always put on top of the stack while the previous is pushed down. This even holds true for an Activity that already exists in the stack. If started again, a new instance will be created while the previous still remains. However, you may decide to override this behaviour. Perhaps you want your app to use only one instance of a certain Activity or for the stack to be cleared when an Activity containing your app’s login screen is started. This can all be achieved through various launch modes. You can define Activity launch behaviour either through your app’s manifest or by adding flags when creating a new intent (an argument for startActivity()).
Note. Depending on your desired launch behaviour, it may only be achievable with either intent flags or by editing your app’s manifest.
Breaking Down Intent Flags
There are three primary intent flags you should familiarize yourself with as these are the ones most often used.
FLAG_ACTIVITY_NEW_TASK: This flag is used to start a new task. However, if there already exists a task with the specified Activity in it, that task is brought to the foreground with the Activity receiving the Intent in the onNewIntent() method.
FLAG_ACTIVITY_SINGLE_TOP: If the specified Activity already exists at the top of the stack (the current Activity), then the Intent is received in onNewIntent(). Otherwise a new instance is started.
FLAG_ACTIVITY_CLEAR_TOP: If the Activity already exists in the current task, every other Activity on top if it is destroyed. The specified Activity is then brought to the top and resumed. The intent is received in onNewIntent().
Breaking Down Launch Modes
Activity launch modes can be configured in your app’s manifest with the launchMode attribute within an activity element. There are four launch modes you can use.
- standard: The standard launch mode is the default behavior. A new instance of the Activity will be launched regardless if it already exists in the current back stack.
- singleTop: If an instance of the Activity already exists at the top of the stack (current Activity), the intent is received in onNewIntent(). However, this occurs ONLY if the Activity is on top of the stack. If it already exists in the current task, but is not on top, a new instance is instantiated with the previous remaining.
- singleTask: The Activity is launched in a new task as the root. However, if it already exists in another task, the intent is received in onNewIntent(). Only one instance of an Activity with “singleTask” can exist.
- singleInstance: Similar to “singleTask”, the difference here is that the Activity is the sole member of its task. Any other activities launched from this Activity will be created in a new task.
Knowing how the back stack works is a fundamental concept for Android developers. When I first started with Android, I’m pretty sure I left all of my activities using the “standard” launch mode along with zero use of intent flags. You can guess how much of a mess that was. Hopefully now you can see how easy the back stack is to understand and manage.