The Back Stack
Okay, you’ll have to use your imagination here.
Imagine that a jukebox piled all of its records in a stack, one on top of the other.
Here’s that imaginary jukebox. Records are piled one on top of the other. Records are accessed in the order of last in, first out
So if you made a request and it wasn’t for the top record, then our friend the jukebox would start chucking records off the top of the pile until it found the one that you wanted.
You can also add new records to the jukebox by putting them on top of the pile. No worries if there’s no more room, the jukebox would simply start chucking records away, starting from the bottom of the pile.
The Back Stack works pretty much like this imaginary jukebox.
Start an app and it starts an activity in a task – more on the task later. Each newly started activity is placed on top of the pile, or stack. Pressing the Back button pops the top activity off the stack, destroying it and exposes the one below.
If the system runs out of memory, then it starts destroying the unused activities, starting from the bottom of the pile.
An app is usually made up of a number of activities. Pressing the app icon starts the app by starting the main activity. It’s known as the root activity. As the user navigates through the app, more activities are started and placed on top of the back stack, with previous ones going into the background.
This collection of activities, performing the different functions of the app, is known as a task.
Most tasks are started from the home screen when a user touches an app’s launcher icon. If the task is currently running in the background then it is brought to the foreground. If it’s not running, then a new task is started with the app’s main activity as the root activity in the stack.
Tasks are like the lanes of a highway. Activities are like cars on the highway, each travelling in a separate lane. A stack (or Back Stack) is like a convoy travelling in the same lane. Occasionally some vehicles from another lane may join the convoy
As new activities are started, they are placed on top of the stack. Pressing the Back button pops the top activity off the stack, destroying it. The one below then resumes and comes into focus. The task no longer exists when all the activities are removed from the stack.
Tasks are a cohesive unit. The whole task will move into the background when another task is in the foreground. It returns to the foreground when the user resumes the task by selecting it in the Overview Screen.
Check the Overview Screen to see which tasks are running. Touch the task to bring it to the foreground
Activities are arranged in the back stack in the order that they are started, first in, last out. They are never rearranged.
You can start activities from anywhere in an app, even from another task. The default behaviour is to start a new instance of the activity which places it on top of the stack. The result is that you can have many versions of the same activity in the same back stack.
You can modify this default behaviour.
Enter the Ninja! Managing tasks
The default behaviour is for all activities in the same task to be placed in the same stack in the order in which they are started.
Warning from the minister of health!
Although you can interrupt the normal behaviour, this shouldn’t be necessary for most apps. If you do change the default behaviour, check that the Back navigation works as expected.
So, here’s how you mess with the normal flow…
Blast off! Launch mode
The launch mode defines how new instances of an activity are associated with the current task.
There are two ways that you can define the different launch modes:
- In the manifest when declaring the activity
- By using flags in the intent used in startActivity()
Make a note: Activities are started by Intents!
You may want to read, Intents and Intent Filters if you haven’t already done so.
Anything to declare? The manifest
Use the <activity> element’s launchMode attribute to declare the activity’s launch mode in the manifest.
launchMode specifies how the activity should be launched into a task:
- android:launchMode=”standard” – This is the default. It creates a new instance of an activity in the task from which it was started and routes the intent to it. You can create the same activity multiple times in the same task as well as in different tasks.
- android:launchMode=”singleTop” – In this case, if the activity already exist at the top of the task’s back stack, then the system routes the intent to it by calling the activity’s onNewIntent() method. It does not create a new activity. With this setting, you can create multiple versions of the same activity in the same task or in different tasks but only if it does not already exist at the top of the stack. If a new activity is created, then onNewIntent() is not called.
- android:launchMode=”singleTask” – Here, the system creates a new task with this new activity at its root. However, if the activity already exists in another task, then the system routes the intent to that activity’s onNewIntent() method and does not create a new instance of the activity. Only one instance of the activity can exist at a time. If you press the BACK button and the activity is in another task then that task’s whole back stack is brought forward and put on top of the current task’s back stack.
- android:launchMode=”singleInstance” – This is the same as singleTask but there can only be one instance of the activity in the task. No other activities will be created in the task. Any activities opened by this activity will be opened in a new task.
Here’s an example.
This is how you would define the FlickerWeb activity in the AndroidManifest.xml file if you want it to be started by a specific intent which matches the intent filter:
This activity will be launched by an intent containing a matching action, category and data. It’s re-launched if it already exists in which case its onNewIntent() method will be triggered and not onCreate()
And here’s how you would start it in code:
This will start the activity in a new task. If it’s already running then that task is brought to the foreground and the activity’s onNewIntent() method is executed
Flag waving: The Flags
You can use flags to modify the default behaviour of how an activity will be associated with a task when using startActivity() to start the activity:
- FLAG_ACTIVITY_NEW_TASK – This starts the activity in a new task. If it’s already running in a task, then that task is brought to the foreground and the activity’s onNewIntent() method receives the intent (this is the same as using singleTask in the manifest)
- FLAG_ACTIVITY_SINGLE_TOP – In this case, if the activity is currently at the top of the stack, then its onNewIntent() method receives the intent. A new activity is not created (this is the same as using singleTop in the manifest).
- FLAG_ACTIVITY_CLEAR_TOP – Here, if the activity is already running in the current task, then this activity is brought to the top of the stack (all others above it are destroyed) and its onNewIntent() method will receive the intent. There is no launchMode equivalent for this flag.
Make a note: You can use the Intent Flags to override the launch mode defined in the manifest file!
Second time around: The onNewIntent() method
This method is called instead of onCreate() in activities that are re-launched. It’s not called when they are created for the first time.
It receives the intent that was used to re-launch it as a parameter.
Check out The Activity Lifecycle tutorial to see which other methods are called during the activity’s lifecycle.
You may also be interested in
I hope that you found this tutorial helpful.