Hi.You may have noticed from the title of the topic that it will be about how Tasks and Back Stack in Android are organized. This article will be a free translation of of the official source The topic is more oriented to beginners, but I think an experienced developer can learn something new as well, since the topic is specific and we don’t often have to customize the behavior of our Activity.
So. Every Android application, at a minimum, consists of a fundamental system object, the Activity. An Activity is a separate screen that has its own logic and UI. The number of activities in an app can vary, from one to many. When switching between the different activities, the user can always return to the previous, closed Activity by pressing the back button on the device. This logic is implemented by using the Activity Stack. Its organization is "last in, first out" – i.e., last in, first out. When a new Activity is opened, it becomes a vertex, while the previous one goes to the stop mode. The stack cannot be shuffled, it has the ability to add a new Activity to the top and remove the top current Activity. The same Activity can be in the stack as many times as you want.
Task is a set of Activities. Each Task contains its own stack. In the default situation, each application has its own task and its own stack. When the application is minimized, the task goes to background, but it does not die. It keeps its entire stack, and the next time the application is opened through the manager or launcher, the existing task will be restored and continue to work.
Below I show a picture of how the stack works.
If you keep pressing back, the stack will delete the Activity until the main root one remains. If the user presses back on it, the application will close and the task will die. By the way, I was saying that when we minimize our application and start e.g. a new one, our task just goes to background and waits until we call it. There is in fact one "but". If we have a lot of tasks in the background or just loading our device too much, it is not unlikely that the task will die because of the lack of system resources. It is not a war of course, but we will lose all our current data and our stack will be cleaned up, that’s for sure. By the way, to avoid losing data in such a case, you should read about SavingActivityState
A small total
All of what we described above is standardbehavior for an Android app. In most cases, this is how it should be. But if you still want to change something, there are possibilities to do so. They will be described further on, but for now a small summary of what we have already discussed.
- On startup, the new Activity moves to the top of the stack, displacing the current one
- When the application is minimized, the task goes to background and stores its state. The task is restored with its stack when the application is restarted again
- Pressing back deletes the current Activity irretrievably. The previous activity is put on top of the stack
- One and the same Activity can have any number of instances in the stack
There are two ways to change the default organization of the Tasks. We can set special attributes in the manifest for each Activity. We can also set special flags for the Intent that starts the new Activity with startActivity(). Note that sometimes the attributes in the manifest and the flags in Intent can contradict each other. In this case, the Intent flags will take precedence.
You can specify a launchMode attribute for each Activity in the manifest. It has several values :
- standard – (default) when you start an Activity, a new instance is created in the stack. An Activity can be placed on the stack more than once
- singleTop – Activity can be stacked more than once. A new entry in the stack is created only if this Activity is not located at the top of the stack. If it is currently a vertex, the onNewIntent() method is triggered, but it is not recreated
- singleTask – Creates a new task and sets the Activity root for it, but only if there is no instance of this Activity in any other task. If the Activity is already located in any task, that particular instance will open and the onNewIntent() method will be called. It becomes the master in due time, and all upper instances are removed, if any. Only one instance of such an Activity can exist
- singleInstance – the same as singleTask, but the Activity will always have a separate task and will be the root task of it. This flag indicates that the Activity will be the one and only member of its own task
It doesn’t really matter in which task a new Activity is open. When you press back, we will still return to the previous task and the previous Activity. The only thing to keep in mind is the singleTask parameter. If when we open such an Activity we take it out of another background task, we completely switch to it and its stack. the picture below demonstrates this.
As I said, we can set special flags for Intent, which starts a new Activity. Flags are of higher priority than launchMode. There are several flags :
- FLAG_ACTIVITY_NEW_TASK – Starts an Activity in a new task. If there already exists a task with an instance of this Activity, this task becomes active, and the onNewIntent() method is triggered.
This flag is similar to the singleTop parameter described above
- FLAG_ACTIVITY_SINGLE_TOP – If the Activity starts itself, i.e. it is at the top of the stack, the onNewIntent() method is called instead of creating a new instance in the stack.
This flag is similar to the singleTop parameter, described above
- FLAG_ACTIVITY_CLEAR_TOP – If an instance of the given Activity already exists in the stack of the given task, all Activity on top of it will be destroyed and that instance will become the top of the stack. It also calls onNewIntent()
By default, all the Activity of our application work in the same task. If we want, we can change this behavior and specify that the activities in one application work in different tascas, or that the activities of different applications work in the same one. To do this, we can specify the name of the taskAffinity parameter in the manifest for each Activity. This is a string value which must not coincide with the name of the package, since the standard task of the application is named exactly as our package. In general, this parameter indicates that it is guaranteed that the Activity will open in its own separate task. This parameter is relevant if we set FLAG_ACTIVITY_NEW_TASK flag or allowTaskReparenting="true" attribute for the Activity. This attribute indicates that the Activity can move between the task that started it and the task that is specified in taskAffinity, if one of them becomes active.
Cleaning the stack
If a task has been in background for a long time, the system cleans its stack by itself, leaving only the root Activity. This behavior is caused by the fact that the user can forget what he did in the application before and probably logs in again for a different purpose. This logic can also be changed with a few attributes in the manifest.
- alwaysRetainTaskState – if the flag is set to true for the root Activity, then the stack will not be cleared and will be fully recovered even after a long time
- clearTaskOnLaunch – If the flag is set to true for the root Activity, the stack will be cleared instantly as soon as the user leaves the task. The exact opposite of alwaysRetainTaskState
- finishOnTaskLaunch – works similarly to clearTaskOnLaunch, but can be set on any Activity and remove it from the stack
This is all for this topic. The article is not improvised, but is essentially a free translation of official documentation I recommend putting together a light example and experimenting with flags and attributes. Some points, personally for me, were unexpectedly interesting. any errors and omissions will be taken into account in ls. Thank you.