task

A task (stack) is a collection of activities that are added to the corresponding task stack each time an Activity is opened. When you press the back key, the activities in the stack will go one step at a time back to the previous interface. Note: This is not an application, but a task. If an application currently has two tasks, there will be two screenshots of the same name in this interface, as shown below:


Log.i(TAG, "Current taskId is$taskId");
Copy the code

Tasks are classified into foreground tasks and background tasks. Foreground tasks can be superimposed and displayed in sequence during rollback. Foreground tasks are not superimposed after entering the background. Foreground Task To access the background, press the home button or the multi-task button. Here’s an example: Now there are 4 ActivityD, C, B, A from top to bottom, A and B are in one task stack, C and D are in one task stack, directly press the back button, D, C, B and A will be out of the stack and back to the desktop. If you press the multi-task button and then cut back, press the back button. At this time, the task stack where A and B are has been converted to the background task stack, so D and C will be out of the stack and return to the desktop.

launchMode

This is the launch mode of the Activity, which can be specified for the Activity in the manifest. There are four types:

launchMode instructions
standard By default, a new Activity instance is created each time an Intent request is made
singleTop Top of stack reuse mode, if the Activity is currently at the top of the caller’s stack, it is directly reused and refreshed using onNewIntent
singleTask In-stack reuse pattern. If the required task stack already exists and there is an example of the Activity in the stack, it will be reused directly, and will simultaneously remove all activities above the Activity in the stack. Create an Activity if it is launched with only the required task stack and no Activity. If there is no desired task stack when it is started, create a new task stack and a new Activity sample.
singleInstance Single example mode, exclusive to a task stack, and stack reuse

1 standard

By default, a new Activity instance is created each time an Intent request is made.

Usage scenario: Most activities with no special requirements are in this mode.

2 singleTop

Top of stack reuse mode, if the Activity is currently at the top of the caller’s stack, it is reused directly and the data is refreshed using the onNewIntent callback. The onCreate, onStart, and other lifecycle methods are not used because they are not created. If the Activity already exists but is not at the top of the stack, a new instance is still created.

3 singleTask

In stack reuse pattern, you can specify the task stack name using taskAffinity. There are three types of startup:

(1) If the required task stack already exists and there is an example of this Activity in the stack, it will be directly reused, and will simultaneously remove all activities above this Activity in the stack;

(2) Create an Activity if it is launched with only the required task stack and no Activity.

③ If there is no required task stack when it is started, create a new task stack and a new Activity example.

Usage scenario: Used to provide some common functions for other applications, such as sharing, file processing, and so on.

4 singleInstance

Single example mode, exclusive to a task stack, and stack reuse.

The usage scenario is similar to singleTask.

taskAffinity

Specifies the name of the task stack required by the Activity. If this is not set, the package name is applied by default. Since the task stack of Standard and singleTop is determined by the Activity that starts it (the same stack as the Activity that starts it), this attribute is useless for standard and singleTop activities. We set this property for two purposes: (1) to specify that an Activity is different from other Activity stacks; ② Specify that several activities share the same stack. The singleInstance Activity’s stack is never the same as any other Activity and does not share the stack with any other Activity, so this property is also meaningless in singleInstance mode. To sum up, this property will only work with singleTask mode and allowTaskReparenting. This property is useful when starting an Activity with FLAG_ACTIVITY_NEW_TASK’s Intent and specifies the name of the task stack that the Activity needs.

allowTaskReparenting

Whether to allow the Activity to move again. Default: False. An Activity instance will default to one stack without moving, but this can happen when allowTaskReparenting is set to true and a Task starts with the same taskAffinity for the Activity.

Here’s an example: APP A calls the mailer Activity in the mail APP (allowTaskReparenting is true). At this point, the mailer Activity belongs to the same Task as its caller. If you click the email APP icon again from the desktop, Under normal circumstances, you will see the MainActivity of the mail APP. Since the writing of mail Activity has been started at this time, it will be transferred to the Task of the mail APP. Users can click the mail APP to directly see the half-written content, which is a good experience. This property is appropriate if an Activity needs to be opened by another APP and also needs to be seen when its own APP is opened. However, this property does not work on Android 9.0 and Android10.0, so use it with caution.

The Intent of the Flags

When launching an Activity with an Intent, you can also influence the mode in which the Activity is launched by setting the Intent. Such as:

val intent = Intent(this, Activity1::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent);
Copy the code

You can set the start mode of an Activity by setting the Flags of the Intent with Java code and specifying it in the manifest. However, the Java (Kotlin) code has a higher priority when setting the start mode of an Activity. Manifest cannot set FLAG_ACTIVITY_CLEAR_TOP, and Java code cannot implement singleInstance. The following are some common flags:

FLAG_ACTIVITY_NEW_TASK

“SingleTask” is underlined because the statement is wrong, the official document is wrong, and so are many bloggers following the official document.

FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP with singleTask this is wrong. The following describes several examples of code experiments that show why it is wrong.

Case 1: TaskAffinity and launchMode are not enabled for both ActivityA and B, A uses FLAG_ACTIVITY_NEW_TASK to enable B, and B uses FLAG_ACTIVITY_NEW_TASK to enable A. The final stack from top to bottom is: A, B, A. The result shows that A is not reused, so A does not execute onNewIntent, and A is recreated. If launchMode is A singleTask, then the end result should be only A in the stack because B is unstacked and A’s onNewIntent is executed because A is reused.

Situation 2: ActivityA and B both set taskAffinity to test and do not set launchMode. MainActivity uses FLAG_ACTIVITY_NEW_TASK to open A. A then uses FLAG_ACTIVITY_NEW_TASK to open B, and there are two tasks, the default Task for MainActivity and the test Task for A and B, all as expected. If you continue to open A with FLAG_ACTIVITY_NEW_TASK in B at this point, you will see nothing. A is not reused, A is not re-opened, and B is not unstacked. If it is A singleTask, there should be 2 tasks, the first is the Task where Main is located, and the second Task has only A, because B is off the stack and A will be reused. FLAG_ACTIVITY_NEW_TASK and singleTask are inconsistent in both cases, and FLAG_ACTIVITY_NEW_TASK itself is inconsistent in both cases (in both cases, SingleTask performance is consistent). FLAG_ACTIVITY_NEW_TASK and singleTask are incorrect

Code below with the experimental results demonstrate why singleTask and FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP is not the same. ActivityA and B both set taskAffinity to test and do not set launchMode. The following open operation is using FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP, A first open the B, B to open A, the result is only A, B is out of the stack stack does seem like singleTask, However, in this case, A is recreated, not reused, and does not execute onNewIntent, which is still different from singleTask.

After seeing this result, I thought at first that my Xiaomi phone system was changed by magic, which caused the bug. Later, I tried the simulator with AS, and the result was the same on Android7.0 and Android 11, which made me confused. FLAG_ACTIVITY_NEW_TASK is not used very much at this point, but is mostly used to start activities from non-activity contexts such as services. Official documents unreliable, many blogs are copied official documents, read the source can only read.

FLAG_ACTIVITY_SINGLE_TOP

With singleTop

FLAG_ACTIVITY_CLEAR_TOP

The official documentation description is incorrect.

When an Activity with this flag bit is started, it is removed from the stack, including itself and all activities above it, and an instance is created at the top of the stack again. FLAG_ACTIVITY_CLEAR_TOP is most commonly used in conjunction with FLAG_ACTIVITY_NEW_TASK. By combining these two flags, you can find existing activities in other tasks and remove all activities from the stack. Create another instance at the top of the stack. Using this flag bit does not accomplish the purpose of reusing the Activity.

FLAG_ACTIVITY_FORWARD_RESULT

When you start an Activity with this flag bit, the setResult of the newly started Activity is returned directly to the previous level. Example: A startActivityForResult opens B, B opens C with this flag bit, and C’s setResult passes over B and is directly returned to A (onActivityResult receives it). It is important to note that you should not use startActivityForResult when starting an Activity with this flag bit, because using this flag bit means that the Activity does not want to process the result returned, so please return it directly to the previous level. Is inconsistent with startActivityForResult. If you have a long list of startActivityForResult you can use this flag bit to simplify things so that the Activity in the middle does not have to process onActivityResult.