First, the startup mode
Introduction to Google Docs:
The launch mode allows you to define how a new instance of an Activity is associated with the current Task. You can define different startup modes in two ways:
Using the manifest file
When you declare an Activity in the manifest file, you can specify how the Activity is associated with tasks when it starts.
Using Intent tags
When you call startActivity(), you can add a flag in the Intent that declares how (or whether) the new Activity is associated with the current Task.
Therefore, if Activity A starts Activity B, Activity B can define in its manifest how to associate with the current Task (if any), and Activity A can request how Activity B should associate with the current Task. If both activities define how Activity B should associate with A Task, Activity A’s request (defined in the intent) is followed in preference to Activity B’s request (defined in the manifest).
Note: Some launch modes can be defined in the manifest file but not in the intent flag, and some launch modes can be defined in the Intent flag but not in the manifest.
Use the manifest file
When you declare an Activity in the manifest file, you can use the launchMode attribute of the < Activity > element to specify how the Activity should be associated with a Task.
The launchMode property describes how the Activity should be launched into the Task. LaunchMode is defined as follows:
<! -- Specify how an activity should be launched. See the <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back
Stack</a> document for important information on how these options impact
the behavior of your application.
<p>If this attribute is not specified, <code>standard</code> launch
mode will be used. Note that the particular launch behavior can
be changed in some ways at runtime through the
{@link android.content.Intent} flags
{@link android.content.Intent#FLAG_ACTIVITY_SINGLE_TOP},
{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}, and
{@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK}. -->
<attr name="launchMode">
<enum name="standard" value="0" />
<enum name="singleTop" value="1" />
<enum name="singleTask" value="2" />
<enum name="singleInstance" value="3" />
<enum name="singleInstancePerTask" value="4" />
</attr>
Copy the code
There are five launmodes:
Standard, singleTop, singleTask, singleInstance, singleInstancePerTask.
If the launchMode attribute is not specified, the default is Standard mode. Note that at runtime a particular launch mode may be changed by the Intent flag.
1 standard
1.1 standard definition
<! -- Thedefault mode, which will usually create a new instance of
the activity when it is started, though this behavior may change
with the introduction of other options such as
{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK
Intent.FLAG_ACTIVITY_NEW_TASK}. -->
<enum name="standard" value="0" />
Copy the code
1), slag turn:
By default, a new instance is typically created when the Activity starts, although this behavior may change with the introduction of other options, such as intent.flag_activity_new_task.
2) Google Document definition:
“Standard” (default mode)
The default value. The system creates a new instance of the Activity in the task that starts the Activity and passes the intent to the instance. An Activity can be instantiated multiple times, each instance belonging to a different task, and each task can have multiple instances.
1.2 Standard Application
Create a new Activity with the launchMode declaration standard Activity.
Starting with MainActivity and starting StandardActivity, the stack looks like this:
[0,0] bounds=[0,0][1920,1200] #1 Task= Task type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #1 ActivityRecord{9aefb8a u0 com.test.la un ch mo de/.StandardActivity t83} type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #0 ActivityRecord{3c3ba3c u0 com.test.la UN Ch mode /.MainActivity t83} type=standard mode=fullscreen override-mode=undefined requite-bounds =[0,0][0,0] Bounds = [0, 0] [1920120]Copy the code
Try starting a new instance of StandardActivity again and the stack looks like this:
Task= Task type=standard mode=fullscreen override-mode=undefined requester-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #2 ActivityRecord{9542c1 u0 com.test.la un ch mo de/.StandardActivity t83} type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #1 ActivityRecord{9aefb8a u0 com.test.la UN Ch mo /.StandardActivity t83} type=standard mode=fullscreen override-mode=undefined requision-bounds =[0,0][0,0] Bounds =[0,0][1920,1200] #0 ActivityRecord{3c3ba3c u0 com.test.la UN ch mo de/.mainactivity t83} type=standard Mode = fullscreen override - mode = undefined requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120]Copy the code
Instances of StandardActivity can be created multiple times, so a new instance of StandardActivity, StandardActivity2, is created and is at the top of the current Task.
2 singleTop
2.1 singleTop definition
<! -- If, when starting the activity, there is already an instance of the same activityclass in the foreground that is
interacting with the user.then
re-use that instance. This existing instance will receive a call to
{@link android.app.Activity#onNewIntent Activity.onNewIntent()} with
the new Intent that is being started. -->
<enum name="singleTop" value="1" />
Copy the code
1), slag turn:
When you start an Activity, you already have an instance of the same Activity interacting with the user in the foreground, so reuse that instance. The existing instance will receive a call to activity.onnewintent ()} with the Intent being launched.
2) Google Document definition:
“singleTop”
If an instance of the Activity already exists at the top of the current task, the system passes the intent to that instance by calling its onNewIntent() method, rather than creating a new instance of the Activity. An Activity can be instantiated multiple times, each instance can belong to a different task, and a task can have multiple instances (but only if the Activity returned to the top of the stack is not an existing instance of that Activity).
For example, suppose the return stack of A task contains the root Activity A along with Activities B, C, and D at the top (stack a-B-C-D; D at the top). Received an intent that targets type D activities. If D starts in the default “Standard” mode, A new instance of the class is started and the stack changes to A-B-C-D-D. However, if D’s launch mode is “singleTop”, an existing instance of D will receive the intent through onNewIntent() because it’s on top of the stack, still a-B-C-D. However, if an intent is received that targets an Activity of type B, a new instance of B is added to the stack, even if its launch mode is “singleTop”.
Note: After creating a new instance of the Activity, the user can press the back button to return to the previous Activity. However, when a new intent is handled by an existing instance of the Activity, the user cannot return to the Activity state before onNewIntent() received the new intent by pressing the back button.
2.2 Practical application of singleTop
Create a new Activity with the launchMode declaration singleTop, SingleTopActivity.
2.2.1 SingleTopActivity is started when the SingleTopActivity instance is in Task Top
Starting with MainActivity, start SingleTopActivity:
Task= Task type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #1 Task= Task type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] [1920,1200] #1 ActivityRecord{3373d6a u0 com.test.launchmode/.SingleTopActivity t85} type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] Bounds =[0,0][1920,1200] #0 ActivityRecord{d66e925u0 Com. Test. Launchmode /. MainActivity t85} type = standard mode = fullscreen override - mode = undefined requested - bounds = [0, 0] [0, 0] Bounds = [0, 0] [1920120]Copy the code
Try starting SingleTopActivity again:
Since there is already an instance of SingleTopActivity at the top of the Task, a new SingleTopActivity will not be started. Instead, the SingleTopActivity instance at the top of the Task receives the activity. onNewIntent callback:
03-01 15:15:45.995 1483 6147 I wm_new_intent: [0222560, 63, 5 com. Test. Launchmode /. SingleTopActivity, NULL, NULL, NULL, 0] 03-01 15:15:46. 028 9926 9926 I wm_on_top_resumed_lost_called: [222456063, com. Test. The launchmode. SingleTopActivity, pausing] 03-01 15:15:46. 029 9926 9926 I wm_on_paused_called: [222456063, com. Test. The launchmode. SingleTopActivity, performPause] 03-01 15:15:46. 029 9926 9926 I launchmode_test: SingleTopActivity#onNewIntent 03-01 15:15:46.030 9926 9926 I wm_on_resume_called: [222456063, com. Test. The launchmode. SingleTopActivity, LIFECYCLER_RESUME_ACTIVITY] 03-01 15:15:46. 030 9926 9926 I wm_on_top_resumed_gained_called: [222456063,com.test.launchmode.SingleTopActivity,topWhenResuming]Copy the code
2.2.2 SingleTopActivity instance starts SingleTopActivity without being in Task Top
Follow 2.2.1 and start a StandardActivity:
Task= Task type=standard mode=fullscreen overrider-mode =undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #2 Task= Task type=standard mode=fullscreen overrider-mode =undefined bounds=[0,0][0,0] [1920,1200] #2 ActivityRecord{7b9e87a u0 com.test.launchmode/.StandardActivity t85} type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] bounds=[0,0][19201200] #1 ActivityRecord{3373d6a u0 com.test.launchmode/.SingleTopActivity t85} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120] # 0 ActivityRecord {d66e925 u0 com. Test. The launchmode /. MainActivity t85} Type =standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200]Copy the code
Finally, try to start SingleTopActivity again when SingleTopActivity is not top:
Task= Task type=standard mode=fullscreen overrider-mode =undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #3 Task= Task type=standard mode=fullscreen overrider-mode =undefined bounds=[0,0][0,0] [1920,1200] #3 ActivityRecord{655dbef u0 com.test.launchmode/.SingleTopActivity t85} type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #2 ActivityRecord{7b9e87au0 com.test.launchmode/.StandardActivity t85} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120] # 1 ActivityRecord {3373 d6a u0 com. Test. The launchmode /. SingleTopActivity T85} type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #0 ActivityRecord{d66e925 u0 com.test.launchmode/.MainActivity t85} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120]Copy the code
In this case, a new instance of SingleTopActivity SingleTopActivity2 will be created because the SingleTopActivity instance SingleTopActivity1 that was started before is not at the top.
3 singleTask
3.1 singleTask definition
<! -- If, when starting the activity, there is already a task running that starts withthis activity, then instead of starting a new
instance the current task is brought to the front. The existing
instance will receive a call to {@link android.app.Activity#onNewIntent
Activity.onNewIntent()}
with the new Intent that is being started, and with the
{@link android.content.Intent#FLAG_ACTIVITY_BROUGHT_TO_FRONT
Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT} flag set. This is a superset
of the singleTop mode, where if there is already an instance
of the activity being started at the top of the stack, it will
receive the Intent as described there (without the FLAG_ACTIVITY_BROUGHT_TO_FRONT flag set). See the
<a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back
Stack</a> document for more details about tasks.-->
<enum name="singleTask" value="2" />
Copy the code
1), slag turn:
When the Activity is started, if there is already a running Task started with the Activity, the Task is moved to the foreground, rather than starting a new instance. The existing instance will receive a call to the activity.onnewintent () method, passing in the Intent that is being launched.FLAG_ACTIVITY_BROUGHT_TO_FRONT is set to intent.flag_activity_brought_to_front. This is a superset of the singleTop pattern.
2) Google Docs:
“singleTask”
The system creates a new task and instantiates the root Activity of the new task. However, if an instance of the Activity already exists in another task, the system forwards the intent to the existing instance by calling its onNewIntent() method, rather than creating a new one. Only one instance of an Activity can exist at a time.
Note: Although the Activity is started in a new task, pressing the back button will still return the user to the previous Activity.
As another example, the Android browser application specifies the singleTask launch mode in the element, thus declaring that the Web browser Activity should always be opened in its own task. This means that if your app issues an intent that opens the Android browser, the system does not place its Activity in the task that your app is in. Instead, it launches a new task for the browser, and if the browser already has a task running in the background, it moves that task to the foreground to handle the new intent.
Whether the Activity is started in a new task or in the same task as the Activity that started it, the user presses the back button to return to the previous Activity. However, if you start an Activity with the specified singleTask startup mode and an instance of the Activity already exists in a background task, the system will forward the entire background task to the foreground. At this point, the back stack contains all the activities from the tasks brought to the foreground, which are at the top of the stack. Figure 4 shows the scenario in detail.
Figure 4. Illustration of the process of adding an Activity to the return stack with a “singleTask” launch mode. If the Activity already exists in a background task that has its own return stack, the entire return stack is also rolled to the foreground, overwriting the current task.
For details on how to set the launchMode in the manifest file, refer to the element’s documentation, which details the launchMode property and acceptable values.
Note: The behavior that you specify for your Activity through the launchMode attribute can be replaced with the flag contained in the intent that launches the Activity.
3.2 Practical application of singleTask
Create a new Activity with the launchMode declaration singleTask, SingleTaskActivity.
3.2.1 start SingleTaskActivity
Start with MainActivity:
Task=100 type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #0 Task=100 type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] [1920,1200] #0 ActivityRecord{14b21d2 u0 com.test.launchmode/.MainActivity t100} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120]Copy the code
Start the SingleTaskActivity:
Task=100 type=standard mode=fullscreen overrider-mode =undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #1 Task=100 type=standard mode=fullscreen overrider-mode =undefined bounds=[0,0][0,0] [1920,1200] #1 ActivityRecord{f14ffea u0 com.test.launchmode/.SingleTaskActivity t100} type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] Bounds =[0,0][19201200] #0 ActivityRecord{14b21d2u0 com.test.launchmode/.MainActivity t100} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120]Copy the code
The new instance is still in Task#100 and does not create a new Task for SingleTaskActivity as expected.
3.2.2 Start SingleTaskActivity when it is already at the top of the current Task
Go to 3.2.1, at this point try starting SingleTaskActivity again:
Since there is already an instance of SingleTaskActivity at the top of the Task, a new SingleTaskActivity will not be started. Instead, the SingleTaskActivity instance at the top of the Task receives the activity. onNewIntent callback:
03-01 17:50:11.789 1483 6167 I wM_new_intent: [0253344, 74100, com. Test. Launchmode /. SingleTaskActivity, NULL, NULL, NULL, 268435456] 03-01 17:50:11. 791 1483 6167 I Wm_task_moved: [100,1,6] 03-01 17:50:11.796 1483 6167 I wm_set_resumed_activity: [0, com. Test. Launchmode /. SingleTaskActivity, positionChildAt] 03-01 17:50:11. 842 15874 15874 I wm_on_top_resumed_lost_called: [253034474, com. Test. The launchmode. SingleTaskActivity, pausing] 03-01 17:50:11. 843 15874 15874 I wm_on_paused_called: [253034474, com. Test. The launchmode. SingleTaskActivity, performPause] 03-01 17:50:11. 843 15874 15874 I launchmode_test: SingleTaskActivity#onNewIntent 03-01 17:50:11.844 15874 15874 I wM_on_resume_called: [253034474, com. Test. The launchmode. SingleTaskActivity, LIFECYCLER_RESUME_ACTIVITY] 03-01 17:50:11. 845 15874 15874 I wm_on_top_resumed_gained_called: [253034474,com.test.launchmode.SingleTaskActivity,topWhenResuming]Copy the code
3.2.3 SingleTaskActivity Starts SingleTaskActivity without being at the top of the current Task
Following 3.2.2, start a StandardActivity:
Task=100 type=standard mode=fullscreen overrider-mode =undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #2 Task=100 type=standard mode=fullscreen overrider-mode =undefined bounds=[0,0][0,0] [1920,1200] #2 ActivityRecord{c901e6c u0 com.test.launchmode/.StandardActivity t100} type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #1 ActivityRecord{f14ffea u0 com.test.launchmode/.SingleTaskActivity t100} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120] # 0 ActivityRecord {14 b21d2 u0 com. Test. The launchmode /. MainActivity t100} Type =standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200]Copy the code
Then try starting SingleTaskActivity again:
Task=100 type=standard mode=fullscreen overrider-mode =undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #1 Task=100 type=standard mode=fullscreen overrider-mode =undefined bounds=[0,0][0,0] [1920,1200] #1 ActivityRecord{f14ffea u0 com.test.launchmode/.SingleTaskActivity t100} type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] Bounds =[0,0][19201200] #0 ActivityRecord{14b21d2u0 com.test.launchmode/.MainActivity t100} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120]Copy the code
The StandardActivity that was started earlier is destroyed, and the SingleTaskActivity is not recreated, but the old instance receives the Activity.onnewintent callback.
03-01 17:52:13.212 1483 1500 I wM_finish_activity: [0210715, 64100, com. Test. Launchmode /. StandardActivity, clear - a task - stack] 03-01 17:52:13. 217 1483 1500 I wm_pause_activity: [0210715, 64, com. Test. Launchmode /. StandardActivity, userLeaving = false, finish] 03-01 17:52:13. 221 1483 1500 I wm_new_intent: [0253344, 74100, com. Test. Launchmode /. SingleTaskActivity, NULL, NULL, NULL, 268435456] 03-01 17:52:13. 222 1483 1500 I Wm_task_moved: [100,1,6] 03-01 17:52:13.310 15874 15874 I wm_on_top_resumed_lost_called: [210771564, com. Test. The launchmode. StandardActivity, topStateChangedWhenResumed] 03-01 17:52:13. 325 15874 15874 I wm_on_paused_called: [210771564, com. Test. The launchmode. StandardActivity, performPause] 03-01 17:52:13. 330 1483 9284 I wm_add_to_stopping: [0210715, 64, com. Test. Launchmode /. StandardActivity, completeFinishing] 03-01 17:52:13. 379 1483 9284 I wm_set_resumed_activity: [0, com. Test. Launchmode /. SingleTaskActivity, resumeTopActivityInnerLocked] 03-01 17:52:13. 470 1483 9284 I wm_resume_activity: [0253344, 74100, com. Test. Launchmode /. SingleTaskActivity] 03-01 17:52:13. 577 15874 15874 I wm_on_restart_called: [253034474, com. Test. The launchmode. SingleTaskActivity, performRestartActivity] 03-01 17:52:13. 577 15874 15874 I wm_on_start_called: [253034474, com. Test. The launchmode. SingleTaskActivity, handleStartActivity] 03-01 17:52:13. 578 15874 15874 I launchmode_test: SingleTaskActivity#onNewIntent 03-01 17:52:13.579 15874 15874 I wm_on_resume_called: [253034474, com. Test. The launchmode. SingleTaskActivity, RESUME_ACTIVITY] 03-01 17:52:13. 579 15874 15874 I wm_on_top_resumed_gained_called: [253034474, com. Test. The launchmode. SingleTaskActivity, topWhenResuming] 03-01 17:52:14. 229 1483 1508 I wm_destroy_activity: [0210715, 64100, com. Test. Launchmode /. StandardActivity, finish - imm: idle] 03-01 17:52:14. 363 15874 15874 I wm_on_stop_called: [210771564, com. Test. The launchmode. StandardActivity, LIFECYCLER_STOP_ACTIVITY] 03-01 17:52:14. 365 15874 15874 I wm_on_destroy_called: [210771564,com.test.launchmode.StandardActivity,performDestroy]Copy the code
FLAG_ACTIVITY_CLEAR_TOP has the same effect as intent.flag_activity_clear_top.
3.2.4 Start SingleTaskActivity with different taskAffinity Settings
In 3.2.1, I thought that when I created SingleTaskActivity, a new Task would be created for it, but actually SingleTaskActivity was started in the existing Task. If the taskAffinity of an Activity matches the rootAffinity member variable of an existing Task, it is possible for the Activity to be launched into the Task and not to create a new Task.
Take a look at the taskAffinity definition:
<! -- Specify a task name that activities have an"affinity" to.
Use with the application tag (to supply a default affinity for all
activities in the application), or with the activity tag (to supply
a specific affinity for that component).
<p>The default value for this attribute is the same as the package
name, indicating that all activities in the manifest should generally
be considered a single "application" to the user. You can use this
attribute to modify that behavior: either giving them an affinity
for another task, if the activities are intended to be part of that
task from the user's perspective, or using an empty string for
activities that have no affinity to a task. -->
<attr name="taskAffinity" format="string" />
Copy the code
Flip: Specifies the name of the Task for which the Activity has affinity. Used with the application tag (which provides a default affinity for all activities in the application) or with the Activity tag (which provides a specific affinity for the component). The default value for this property is the same as the package name, indicating that all activities in the MANIFEST should generally be treated as a single “application” by the user. You can use this property to modify this behavior: if the Activity is part of another Task from the user’s perspective, provide an affinity for another Task for the Activity, or use an empty string for an Activity that is not associated with any Task.
Since SingleTaskActivity does not explicitly specify a taskAffinity property, it uses the default package name, “com.test.launchMode”, so it launches into an existing Task.
Here we modify the taskAffinity property of SingleTaskActivity:
android:taskAffinity="com.single.task"
Copy the code
Starting with MainActivity, try SingleTaskActivity again:
Task= Task type=standard mode=fullscreen overrider-mode =undefined requester-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #0 Task= Task type=standard mode=fullscreen overrider-mode =undefined requester-bounds =[0,0][0,0] [1920,1200] #0 ActivityRecord{e7a99fa u0 com.test.launchmode/.SingleTaskActivity t107} type=standard mode=fullscreen Override-mode =undefined requester-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #6 Task=106 type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] Bounds =[0,0][1920,1200] #0 ActivityRecord{94a375c u0 com.test.launchmode/.MainActivity t106} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120]Copy the code
Sure enough, with a unique taskAffinity set, SingleTaskActivity can be launched into another Task.
3.2.5 SingleTaskActivity is started from the foreground Task when an instance of SingleTaskActivity exists in a background Task
Follow 3.2.4 to start StandardActivity with SingleTaskActivity:
Task= Task type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #1 ActivityRecord{b2c985e u0 com.test.launchmode/.StandardActivity t107} type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #0 ActivityRecord{e7a99fa u0 com.test.launchmode/.SingleTaskActivity t107} type=standard mode=fullscreen override-mode=undefined Requested-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #6 Task=106 type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120] # 0 ActivityRecord {94 a375c u0 com. Test. The launchmode /. MainActivity t106} Type =standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200]Copy the code
The new StandardActivity starts in the Task where the SingleTaskActivity resides.
Then move the Task where the MainActivity resides to the foreground:
Task= Task type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #0 ActivityRecord{94a375c u0 com.test.launchmode/.MainActivity t106} type=standard mode=fullscreen override-mode=undefined Requested-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #5 Task=107 type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120] # 1 ActivityRecord {b2c985e u0 com. Test. The launchmode /. StandardActivity T107} type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #0 ActivityRecord{e7a99fa u0 com.test.launchmode/.SingleTaskActivity t107} type=standard mode=fullscreen Override - mode = undefined requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120]Copy the code
Try again to start SingleTaskActivity via MainActivity:
Task= Task type=standard mode=fullscreen overrider-mode =undefined requester-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #0 Task= Task type=standard mode=fullscreen overrider-mode =undefined requester-bounds =[0,0][0,0] [1920,1200] #0 ActivityRecord{e7a99fa u0 com.test.launchmode/.SingleTaskActivity t107} type=standard mode=fullscreen Override-mode =undefined requester-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #6 Task=106 type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] Bounds =[0,0][1920,1200] #0 ActivityRecord{94a375c u0 com.test.launchmode/.MainActivity t106} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120]Copy the code
SingleTaskActivity’s Task#107 is moved to the foreground, SingleTaskActivity receives the activity. onNewIntent callback, and StandardActivity is killed:
I wm_task_moved: [107,1,7] 03-01 19:10:58.807 1483 1501 I wm_task_to_front: [0,107] 03-01 19:10:58.815 1483 1501 I wm_focused_root_task: [0,0,107,106 bringingFoundTaskToFront] 03-01 19:10:58. 829 1483 1501 I wm_set_resumed_activity: [0, com. Test. Launchmode /. StandardActivity, bringingFoundTaskToFront] 03-01 19:10:58. 833 1483 1501 I wm_finish_activity: [0187719, 66107, com. Test. Launchmode /. StandardActivity, clear - a task - stack] 03-01 19:10:58. 834 1483 1501 I wm_destroy_activity: [0187719, 66107, com. Test. Launchmode /. StandardActivity, finish - imm: finishIfPossible] 03-01 19:10:58. 839 1483 1501 I wm_new_intent: [0242158, 34107, com. Test. Launchmode /. SingleTaskActivity, NULL, NULL, NULL, 268435456] 03-01 19:10:58. 855 1483 1501 I wm_pause_activity: [0155587, 80, com. Test. Launchmode /. MainActivity, userLeaving = true, pauseBackTasks] 03-01 19:10:58. 920 20840 20840 I wm_on_top_resumed_lost_called: [155858780, com. Test. The launchmode. MainActivity, topStateChangedWhenResumed] 03-01 19:10:58. 948 20840 20840 I wm_on_destroy_called: [187471966, com. Test. The launchmode. StandardActivity, performDestroy] 03-01 19:10:59. 080 20840 20840 I wm_on_paused_called: [155858780, com. Test. The launchmode. MainActivity, performPause] 03-01 19:10:59. 169 1483 1501 I wm_set_resumed_activity: [0, com. Test. Launchmode /. SingleTaskActivity, resumeTopActivityInnerLocked] 03-01 19:10:59. 177 1483 1501 I wm_add_to_stopping: [0155587, 80, com. Test. Launchmode /. MainActivity, makeInvisible] 03-01 19:10:59. 216 1483 1501 I wm_resume_activity: [0242158, 34107, com. Test. Launchmode /. SingleTaskActivity] 03-01 19:10:59. 308 20840 20840 I wm_on_restart_called: [242915834, com. Test. The launchmode. SingleTaskActivity, performRestartActivity] 03-01 19:10:59. 309 20840 20840 I wm_on_start_called: [242915834, com. Test. The launchmode. SingleTaskActivity, handleStartActivity] 03-01 19:10:59. 309 20840 20840 I launchmode_test: SingleTaskActivity#onNewIntent 03-01 19:10:59.310 20840 20840 I wm_on_resume_called: [242915834, com. Test. The launchmode. SingleTaskActivity, RESUME_ACTIVITY] 03-01 19:10:59. 310 20840 20840 I wm_on_top_resumed_gained_called: [242915834, com. Test. The launchmode. SingleTaskActivity, topWhenResuming] 03-01 19:11:00. 645 1483 1508 I wm_stop_activity: [0155587, 80, com. Test. Launchmode /. MainActivity] 03-01 19:11:00. 789 20840 20840 I wm_on_stop_called: [155858780,com.test.launchmode.MainActivity,STOP_ACTIVITY_ITEM]Copy the code
The logic for destroying StandardActivity is the same as in 3.2.3.
4 singleInstance
4.1 singleInstance definition
<! -- Only allow one instance ofthis activity to ever be
running. This activity gets a unique task with only itself running
in it; if it is ever launched again with the same Intent, then that
task will be brought forward and its
{@link android.app.Activity#onNewIntent Activity.onNewIntent()}
method called. If this
activity tries to start a new activity, that new activity will be
launched in a separate task. See the
<a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back
Stack</a> document for more details about tasks.-->
<enum name="singleInstance" value="3" />
Copy the code
1), slag turn:
Only one instance of this Activity is allowed to run. The Activity gets a unique Task that runs on its own; If it starts again with the same Intent, the Task is moved to the foreground and its activity.onnewintent () method is called. If the Activity attempts to start a new Activity, the new Activity will be started in a separate Task.
2) Google Docs:
“singleInstance”
Similar to “singleTask”, the only difference is that the system does not start any other activities into the task that contains the instance. The Activity is always the only member of its task; Any activities that are started by this Activity are opened in other tasks.
4.2 singleInstance Application
Create a new Activity with the launchMode declaration singleInstance, SingleInstanceActivity.
2 start SingleInstanceActivity
Start with MainActivity:
Task= Task type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #0 Task= Task type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] [1920,1200] #0 ActivityRecord{a19254e u0 com.test.launchmode/.MainActivity t94} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120]Copy the code
Start the SingleInstanceActivity:
[0,0] bounds=[0,0][1920,1200] #0 Task= Task type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #0 ActivityRecord{3211027 u0 com.test.launchmode/.SingleInstanceActivity t95} type=standard mode=fullscreen Override-mode =undefined requester-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #6 Task=94 type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] Bounds =[0,0][19201200] #0 ActivityRecord{a19254e u0 Com. Test. Launchmode /. MainActivity t94} type = standard mode = fullscreen override - mode = undefined requested - bounds = [0, 0] [0, 0] Bounds = [0, 0] [1920120]Copy the code
A new Task#95 is created for the newly launched SingleInstanceActivity, and the Task#95 is moved to the foreground.
4.2.2 Try to create a new SingleInstanceActivity instance in a Task that is not SingleInstanceActivity
Switch to Task#94 where the MainActivity is located:
[0,0] bounds=[0,0] bounds=[0,0][1920,1200] #0 Task= Task type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[1920,1200] #0 ActivityRecord{eea3b93 u0 com.test.launchmode/.MainActivity t94} type=standard mode=fullscreen override-mode=undefined Requested-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #6 Task=95 type=standard mode=fullscreen override-mode=undefined Requisition-bounds =[0,0][0,0] Bounds =[0,0][1920,1200] #0 ActivityRecord{3211027u0 com.test.launchmode/.SingleInstanceActivity t95} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120]Copy the code
Try starting SingleInstanceActivity again in the MainActivity interface:
[0,0] bounds=[0,0][1920,1200] #0 Task= Task type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #0 ActivityRecord{3211027 u0 com.test.launchmode/.SingleInstanceActivity t95} type=standard mode=fullscreen Override-mode =undefined requester-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #6 Task=94 type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #0 ActivityRecord{eea3b93 u0 Com. Test. Launchmode /. MainActivity t94} type = standard mode = fullscreen override - mode = undefined requested - bounds = [0, 0] [0, 0] Bounds = [0, 0] [1920120]Copy the code
Task#95 of the previously created SingleInstanceActivity instance is moved to the foreground without creating a new instance.
4.2.3 Try to create a new SingleInstanceActivity instance in the SingleInstanceActivity Task
Proceed to 4.2.2 and try starting SingleInstanceActivity again:
The result is that no new instance is created, only SingleInstanceActivity receives the activity. onNewIntent callback:
03-01 16:34:55.132 1483 1710 I wm_new_intent: [0524847 1 remarks, com. Test. Launchmode /. SingleInstanceActivity, NULL, NULL, NULL, 268435456] 03-01 16:34:55. 135 1483 1710 I Wm_task_moved: [95,1,7] 03-01 16:34:55.142 1483 1710 I wm_set_resumed_activity: [0, com. Test. Launchmode /. SingleInstanceActivity, positionChildAt] 03-01 16:34:55. 195 12995 12995 I wm_on_top_resumed_lost_called: [52498471, com. Test. The launchmode. SingleInstanceActivity, pausing] 03-01 16:34:55. 196 12995 12995 I wm_on_paused_called: [52498471, com. Test. The launchmode. SingleInstanceActivity, performPause] 03-01 16:34:55. 196 12995 12995 I launchmode_test: SingleInstance#onNewIntent 03-01 16:34:55.196 12995 12995 I wm_on_resume_called: [52498471, com. Test. The launchmode. SingleInstanceActivity, LIFECYCLER_RESUME_ACTIVITY] 03-01 16:34:55. 196 12995 12995 I wm_on_top_resumed_gained_called: [52498471,com.test.launchmode.SingleInstanceActivity,topWhenResuming]Copy the code
4.2.4 Start other Activities in the Task where the SingleInstanceActivity resides
Start with SingleInstanceActivity:
[0,0] bounds=[0,0] bounds=[0,0][1920,1200] #0 Task= Task type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[1920,1200] #0 ActivityRecord{e074c42 u0 com.test.launchmode/.SingleInstanceActivity t98} type=standard mode=fullscreen Override - mode = undefined requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120]Copy the code
Start the StandardActivity:
#7 Task=99 type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #0 ActivityRecord{47012ae u0 com.test.launchmode/.StandardActivity t99} type=standard mode=fullscreen Override-mode =undefined requester-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #6 Task=98 type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #0 ActivityRecord{e074c42 u0 com.test.launchmode/.SingleInstanceActivity t98} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120]Copy the code
StandardActivity is started in a new Task, Task#99.
5 singleInstancePerTask
5.1 singleInstancePerTask definition
Added in Android 12.
<! -- The activity can only be running as the root activity of the task, the first activity that created the task, and therefore there will only be one instance ofthis activity
in a task. In constrast to the {@code singleTask} launch mode, this activity can be
started in multiple instances in different tasks if the
{@code } or {@code FLAG_ACTIVITY_NEW_DOCUMENT} is set.-->
<enum name="singleInstancePerTask" value="4" />
Copy the code
Slag turn:
This Activity can only be run as the root Activity of a Task, that is, the first Activity created for the Task, so there can only be one instance of this Activity in a Task. In contrast to the singleTask startup mode, if FLAG_ACTIVITY_MULTIPLE_TASK or FLAG_ACTIVITY_NEW_DOCUMENT is set, the activity can be started in multiple instances in different tasks.
5.2 Application of singleInstancePerTask
A new launchMode statement for singleInstancePerTask Activity, SingleInstancePerTaskActivity.
5.2.1 start SingleInstancePerTaskActivity
MainActivity as starting point, start SingleInstancePerTaskActivity:
Task= Task type=standard mode=fullscreen override-mode=undefined requester-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #0 Task= Task type=standard mode=fullscreen override-mode=undefined requester-bounds =[0,0][0,0] [1920,1200] #0 ActivityRecord{91f591f u0 com.test.launchmodetest/.SingleInstancePerTaskActivity t230} type=standard mode=fullscreen Override-mode =undefined requester-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #6 Task=229 type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] Bounds =[0,0][1920,1200] #0 ActivityRecord{37dc04du0 com.test.launchmodetest/.MainActivity t229} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120]Copy the code
See here for the new initiated directly SingleInstancePerTaskActivity created a new Task# 230, without having to set a different taskAffinity for it.
5.2.2 start SingleInstancePerTaskActivity when SingleInstancePerTaskActivity is located in the current Task top
Launched SingleInstancePerTaskActivity 5.2.1, when, and to create a Task# after 230, try restarting SingleInstancePerTaskActivity, Found SingleInstancePerTaskActivity will not be repeated start, but the existing instances received Activity. The onNewIntent callback:
03-03 09:52:423 1490 1723 I wM_new_intent: [0153493, 75230, com. Test. Launchmodetest /. SingleInstancePerTaskActivity, NULL, NULL, NULL, 268435456] 03-03 09:52:40. 025 1490 1723 I wm_task_moved: [230,1,7] 03-03 09:52:40.030 1490 1723 I wm_set_resumed_activity: [0, com. Test. Launchmodetest /. SingleInstancePerTaskActivity, positionChildAt] 03-03 09:52:40. 076 30409 30409 I wm_on_top_resumed_lost_called: [153049375, com. Test. Launchmodetest. SingleInstancePerTaskActivity, pausing] 03-03 09:52:40. 077 30409 30409 I wm_on_paused_called: [153049375, com. Test. Launchmodetest. SingleInstancePerTaskActivity, performPause] 03-03 09:52:40. 077 30409 30409 I Launchmode_test: SingleInstancePerTaskActivity# onNewIntent 03-03 09:52:40. 078 30409 30409 I wm_on_resume_called: [153049375, com. Test. Launchmodetest. SingleInstancePerTaskActivity, LIFECYCLER_RESUME_ACTIVITY] 03-03 09:52:40. 079, 30409 30409 I wm_on_top_resumed_gained_called: [153049375,com.test.launchmodetest.SingleInstancePerTaskActivity,topWhenResuming]Copy the code
When SingleInstancePerTaskActivity 5.2.3 requires not located in the current Task top SingleInstancePerTaskActivity when started
5.2.1, create a StandardActivity through SingleInstancePerTaskActivity first:
Task= Task type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #1 Task= Task type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] [1920,1200] #1 ActivityRecord{eea3628 u0 com.test.launchmodetest/.StandardActivity t230} type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #0 ActivityRecord{91f591fu0 com.test.launchmodetest/.SingleInstancePerTaskActivity t230} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120]Copy the code
And then to start SingleInstancePerTaskActivity:
Task= Task type=standard mode=fullscreen override-mode=undefined requester-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #0 Task= Task type=standard mode=fullscreen override-mode=undefined requester-bounds =[0,0][0,0] [1920,1200] #0 ActivityRecord{91f591f u0 com.test.launchmodetest/.SingleInstancePerTaskActivity t230} type=standard mode=fullscreen Override - mode = undefined requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120]Copy the code
Is StandardActivity be destroyed as a result, SingleInstancePerTaskActivity Activity. The existing instances received onNewIntent callback:
03-03 09:58:44.128 1490 3749 I wM_finish_activity: [0250303, 12230, com. Test. Launchmodetest /. StandardActivity, clear - a task - stack] 03-03 09:58:44. 133 1490 3749 I wm_pause_activity: [0250303 12, com. Test. Launchmodetest /. StandardActivity, userLeaving = false, finish] 03-03 09:58:44. 137 1490 3749 I wm_new_intent: [0153493, 75230, com. Test. Launchmodetest /. SingleInstancePerTaskActivity, NULL, NULL, NULL, 268435456] 03-03 09:58:44. 138 1490 3749 I wm_task_moved: [230,1,7] 03-03 09:58:44.207 30409 30409 I wm_on_top_resumed_lost_called: [250230312, com. Test. Launchmodetest. StandardActivity, topStateChangedWhenResumed] 03-03 09:58:44. 214 30409 30409 I wm_on_paused_called: [250230312, com. Test. Launchmodetest. StandardActivity, performPause] 03-03 09:58:44. 226 1490 2226 I wm_add_to_stopping: [0250303 12, com. Test. Launchmodetest /. StandardActivity, completeFinishing] 03-03 09:58:44. 248 1490 2226 I wm_set_resumed_activity: [0, com. Test. Launchmodetest /. SingleInstancePerTaskActivity, resumeTopActivityInnerLocked] 03-03 09:58:44. 287 1490 2226 I wm_resume_activity: [0153493, 75230, com. Test. Launchmodetest /. SingleInstancePerTaskActivity] 03-03 09:58:44. 369 30409 30409 I wm_on_restart_called: [153049375, com. Test. Launchmodetest. SingleInstancePerTaskActivity, performRestartActivity] 03-03 09:58:44. 369 30409 30409 I wm_on_start_called: [153049375, com. Test. Launchmodetest. SingleInstancePerTaskActivity, handleStartActivity] 03-03 09:58:44. 370 30409 30409 I Launchmode_test: SingleInstancePerTaskActivity# onNewIntent 03-03 09:58:44. 370 30409 30409 I wm_on_resume_called: [153049375, com. Test. Launchmodetest. SingleInstancePerTaskActivity, RESUME_ACTIVITY] 03-03 09:58:44. 370 30409 30409 I wm_on_top_resumed_gained_called: [153049375, com. Test. Launchmodetest. SingleInstancePerTaskActivity, topWhenResuming] 03-03 09:58:44. 969 1490 1515 I wm_destroy_activity: [0250303, 12230, com. Test. Launchmodetest /. StandardActivity, finish - imm: idle] 03-03 09:58:45. 104 30409 30409 I wm_on_stop_called: [250230312, com. Test. Launchmodetest. StandardActivity, LIFECYCLER_STOP_ACTIVITY] 03-03 09:58:45. 105 30409 30409 I wm_on_destroy_called: [250230312,com.test.launchmodetest.StandardActivity,performDestroy]Copy the code
5.2.4 when existing Task SingleInstancePerTaskActivity didn’t at the front desk to start SingleInstancePerTaskActivity
5.2.1, first create a StandardActivity through SingleInstancePerTaskActivity, then put the Task switching to Task# 229:
[0,0] bounds=[0,0][1920,1200] #0 Task= Task type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #0 ActivityRecord{37dc04d u0 com.test.launchmodetest/.MainActivity t229} type=standard mode=fullscreen Override-mode =undefined requester-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #6 Task=230 type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #1 ActivityRecord{db261fd u0 com.test.launchmodetest/.StandardActivity t230} type=standard mode=fullscreen override-mode=undefined Requisition-bounds =[0,0][0,0] Bounds =[0,0][1920,1200] #0 ActivityRecord{91F591fu0 com.test.launchmodetest/.SingleInstancePerTaskActivity t230} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120]Copy the code
And then through Task# 229 MainActivity to start SingleInstancePerTaskActivity:
Task= Task type=standard mode=fullscreen override-mode=undefined requester-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #0 Task= Task type=standard mode=fullscreen override-mode=undefined requester-bounds =[0,0][0,0] [1920,1200] #0 ActivityRecord{91f591f u0 com.test.launchmodetest/.SingleInstancePerTaskActivity t230} type=standard mode=fullscreen Override-mode =undefined requester-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #6 Task=229 type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] Bounds =[0,0][1920,1200] #0 ActivityRecord{37dc04du0 com.test.launchmodetest/.MainActivity t229} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120]Copy the code
Results Task# 230 moved to the front desk and StandardActivity destroyed, SingleInstancePerTaskActivity Activity. The existing instances received onNewIntent callback:
03-03 10:02:35.383 1490 8118 I wm_task_moved: [230,1,7] 03-03 10:02:35.384 1490 8118 I wm_task_to_front: [0,230] 03-03 10:02:35.402 1490 8118 I wm_focused_root_task: [0,0,230,229 bringingFoundTaskToFront] 03-03 10:02:35. 427 1490 8118 I wm_set_resumed_activity: [0, com. Test. Launchmodetest /. StandardActivity, bringingFoundTaskToFront] 03-03 10:02:35. 430 1490 8118 I wm_finish_activity: [0229943, 01230, com. Test. Launchmodetest /. StandardActivity, clear - a task - stack] 03-03 10:02:35. 431 1490 8118 I wm_destroy_activity: [0229943, 01230, com. Test. Launchmodetest /. StandardActivity, finish - imm: finishIfPossible] 03-03 10:02:35. 434 1490 8118 I wm_new_intent: [0153493, 75230, com. Test. Launchmodetest /. SingleInstancePerTaskActivity, NULL, NULL, NULL, 268435456] 03-03 10:02:35. 447 1490 8118 I wm_pause_activity: [0585287 7, com. Test. Launchmodetest /. MainActivity, userLeaving = true, pauseBackTasks] 03-03 10:02:35. 489 30409 30409 I wm_on_top_resumed_lost_called: [58572877, com. Test. Launchmodetest. MainActivity, topStateChangedWhenResumed] 03-03 10:02:35. 513 30409 30409 I wm_on_destroy_called: [229794301, com. Test. Launchmodetest. StandardActivity, performDestroy] 03-03 10:02:35. 562 30409 30409 I wm_on_paused_called: [58572877, com. Test. Launchmodetest. MainActivity, performPause] 03-03 10:02:35. 728 1490 2524 I wm_set_resumed_activity: [0, com. Test. Launchmodetest /. SingleInstancePerTaskActivity, resumeTopActivityInnerLocked] 03-03 10:02:35. 749 1490 2524 I wm_add_to_stopping: [0585287 7, com. Test. Launchmodetest /. MainActivity, makeInvisible] 03-03 10:02:35. 833 1490 2524 I wm_resume_activity: [0153493, 75230, com. Test. Launchmodetest /. SingleInstancePerTaskActivity] 03-03 10:02:35. 949 30409 30409 I wm_on_restart_called: [153049375, com. Test. Launchmodetest. SingleInstancePerTaskActivity, performRestartActivity] 03-03 10:02:35. 949 30409 30409 I wm_on_start_called: [153049375, com. Test. Launchmodetest. SingleInstancePerTaskActivity, handleStartActivity] 03-03 10:02:35. 950 30409 30409 I Launchmode_test: SingleInstancePerTaskActivity# onNewIntent 03-03 10:02:35. 950 30409 30409 I wm_on_resume_called: [153049375, com. Test. Launchmodetest. SingleInstancePerTaskActivity, RESUME_ACTIVITY] 03-03 10:02:35. 951 30409 30409 I wm_on_top_resumed_gained_called: [153049375, com. Test. Launchmodetest. SingleInstancePerTaskActivity, topWhenResuming] 03-03 10:02:37. 430 1490 1515 I wm_stop_activity: [0585287 7, com. Test. Launchmodetest /. MainActivity] 03-03 10:02:37. 829 30409 30409 I wm_on_stop_called: [58572877,com.test.launchmodetest.MainActivity,STOP_ACTIVITY_ITEM]Copy the code
FLAG_ACTIVITY_MULTIPLE_TASK intent.flag_activity_new_document
After analyzing the above four cases, it is found that singleInstancePerTask works almost as well as singleTask. However, singleInstancePerTask does not require a special taskAffinity for the Activity started to create a new Task.
According to singleInstancePerTask, FLAG_ACTIVITY_MULTIPLE_TASK or intent.flag_activity_new_document can be used to instantiate a launched Activity multiple times in multiple tasks. So let’s see what happens. Every time start SingleInstancePerTaskActivity, here are the Intent to start adding the two flag:
intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
Copy the code
Start singleInstancePerTask with MainActivity as the starting point. According to 5.2.1, a Task will be created for the newly started singleInstancePerTask:
Task= Task type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #0 ActivityRecord{3a0de63 u0 com.test.launchmodetest/.SingleInstancePerTaskActivity t236} type=standard mode=fullscreen Override-mode =undefined requester-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #6 Task=235 type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #0 ActivityRecord{766c588 u0 com.test.launchmodetest/.MainActivity t235} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120]Copy the code
Start singleInstancePerTask with singleInstancePerTask:
Task= Task type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #0 Task= Task type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] [1920,1200] #0 ActivityRecord{518568f u0 com.test.launchmodetest/.SingleInstancePerTaskActivity t237} type=standard mode=fullscreen Override-mode =undefined requester-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #7 Task=236 type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #0 ActivityRecord{3a0de63 u0 com.test.launchmodetest/.SingleInstancePerTaskActivity t236} type=standard mode=fullscreen override-mode=undefined Requested-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #6 Task= 297 type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120] # 0 ActivityRecord {766 c588 u0 com. Test. Launchmodetest /. MainActivity T235} type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920 1200]Copy the code
Sure enough, unlike 5.2.2, a new instance of singleInstancePerTask is created and a new Task#237 is created.
Use Intent flags
When you start an Activity, change the default association between the Activity and its Task by adding a flag to the intent of startActivity().
1 FLAG_ACTIVITY_NEW_TASK
1.1 FLAG_ACTIVITY_NEW_TASK definition
/**
* If set, this activity will become the start of a new task on this
* history stack. A task (from the activity that started it to the
* next task activity) defines an atomic group of activities that the
* user can move to. Tasks can be moved to the foreground and background;
* all of the activities inside of a particular task always remain in
* the same order. See
* <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back
* Stack</a> for more information about tasks.
*
* <p>This flag is generally used by activities that want
* to present a "launcher" style behavior: they give the user a list of
* separate things that can be done, which otherwise run completely
* independently of the activity launching them.
*
* <p>When using this flag, if a task is already running for the activity
* you are now starting, then a new activity will not be started; instead,
* the current task will simply be brought to the front of the screen with
* the state it was last in. See {@link#FLAG_ACTIVITY_MULTIPLE_TASK} for a flag * to disable this behavior. * * <p>This flag can not be used when the caller is requesting a result from * the activity being launched. */
public static final int FLAG_ACTIVITY_NEW_TASK = 0x10000000;
Copy the code
If set, the Activity becomes the start Activity in the stack of a new Task. A Task(from the Activity that starts it to the next Task Activity) defines an atomic group of activities that the user can move to. Tasks can be moved to the foreground and background; All activities in a particular Task always remain in the same order.
This flag is commonly used by activities that want to present a “Launcher” style behavior: they give the user a list of individual things they can do that would otherwise run completely independently of the Activity that started them. When using this flag, if a task is already running the activity you started, a new activity will not be started. Instead, the current Task is simply brought to the front of the screen with the state it last entered. See FLAG_ACTIVITY_MULTIPLE_TASK to disable this behavior.
This flag cannot be used when the caller requests a result from the Activity that was started.
2) Google Docs:
FLAG_ACTIVITY_NEW_TASK
Start the Activity in a new Task. If the Activity you start now already has a Task running, the system pushes the Task to the foreground and restores its last state, and the Activity receives the new intent in onNewIntent().
This is the same behavior as the “singleTask” launchMode value.
1.2 FLAG_ACTIVITY_NEW_TASK Actual application
1.2.1 Start the Activity as FLAG_ACTIVITY_NEW_TASK
Here I start StandardActivity directly with MainActivty, and start the Intent with FLAG_ACTIVITY_NEW_TASK:
Task= Task type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #1 Task= Task type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] [1920,1200] #1 ActivityRecord{bf67e76 u0 com.test.launchmode/.StandardActivity t134} type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] Bounds =[0,0][1920,1200] #0 ActivityRecord{887cfac u0 com.test.launchmode/.MainActivity t134} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120]Copy the code
The newly launched StandardActivity does not start as a new Task as expected, but is still created in the current Task#134.
1.2.2 FLAG_ACTIVITY_NEW_TASK When the Activity to be started is already at the top of the Task
Start StandardActivity as FLAG_ACTIVITY_NEW_TASK when there is already a StandardActivity at the top of the current Task, as in 1.2.1:
Task= Task type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #2 Task= Task type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] [1920,1200] #2 ActivityRecord{4ced944 u0 com.test.launchmode/.StandardActivity t193} type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] bounds=[0,0][19201200] #1 ActivityRecord{bf67e76u0 com.test.launchmode/.StandardActivity t134} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120] # 0 ActivityRecord {887 cfac u0 com. Test. The launchmode /. MainActivity t134} Type =standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200]Copy the code
Unlike the launchMode “singleTask” case, where a new instance is created directly, singleTask reuses the old instance.
1.2.3 FLAG_ACTIVITY_NEW_TASK Starts a taskAffinity Activity with a different App package name
According to the Google documentation, FLAG_ACTIVITY_NEW_TASK generates the same behavior as the singleTask in launchMode, so the reason for not creating a new Task should be the same. So I opened a DifferentAffinityActivity here, give it a set a different App taskAffinity package name, Then by MainActivity FLAG_ACTIVITY_NEW_TASK way to start DifferentAffinityActivity:
Task=2 type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #0 Task=2 type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] [1920,1200] #0 ActivityRecord{dc31b80 u0 com.test.launchmodetest/.DifferentAffinityActivity t210} type=standard mode=fullscreen Override-mode =undefined requester-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #6 Task=1 type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] Bounds =[0,0][1920,1200] #0 ActivityRecord{ecDD154u0 com.test.launchmodetest/.MainActivity t209} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120]Copy the code
Successful, the system creates a Task#2 for StandardActivity.
Another test, if only to set up a special taskAffinity DifferentAffinityActivity, set FLAG_ACTIVITY_NEW_TASK but don’t start it, will not create a new Task.
1.2.4 FLAG_ACTIVITY_NEW_TASK in taskAffinity (1)
Start MainActivity first, and then start a StandardActivity via MainActivity as FLAG_ACTIVITY_NEW_TASK. According to 1.2.1, both activities are in the same Task.
Then by StandardActivity FLAG_ACTIVITY_NEW_TASK way to start a different taskAffinity DifferentAffinityActivity, according to 1.2.3, The system will create a new Task for DifferentAffinityActivity:
[0,0] bounds=[0,0][1920,1200] #0 Task= Task type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #0 ActivityRecord{82c008a u0 com.test.launchmodetest/.DifferentAffinityActivity t208} type=standard mode=fullscreen Override-mode =undefined requester-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #6 Task=207 type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #1 ActivityRecord{cdd2a3e u0 com.test.launchmodetest/.StandardActivity t207} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120] # 0 ActivityRecord {9 a2658a u0 com. Test. Launchmodetest /. MainActivity T207} type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920 1200]Copy the code
Task#208 differs from the existing taskAffniity of Task#207, and then in Task#208 we start StandardActivity as FLAG_ACTIVITY_NEW_TASK, StandardActivity’s taskAffinity is consistent with Task#207:
Task= Task type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #2 Task= Task type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] [1920,1200] #2 ActivityRecord{f0d64cb u0 com.test.launchmodetest/.StandardActivity t207} type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #1 ActivityRecord{cdd2a3e u0 com.test.launchmodetest/.StandardActivity t207} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120] # 0 ActivityRecord {9 a2658a u0 com. Test. Launchmodetest /. MainActivity T207} type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #6 Task=208 type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #0 ActivityRecord{82c008a u0 com.test.launchmodetest/.DifferentAffinityActivity t208} type=standard mode=fullscreen Override - mode = undefined requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120]Copy the code
Here we see that StandardActivity2 is not created in Task#208 but in Task#207, which is different from launchMode being “singleTask”, Task#207 does not start a second instance of an Activity that already exists in Task#207.
For comparison, what if we started StandardActivity in Task#208 without FLAG_ACTIVITY_NEW_TASK set:
Here we see StandardActivity2 created directly in Task#208, ignoring the taskAffinity difference.
When an Activity is started in FLAG_ACTIVITY_NEW_TASK, taskAffinity is used to find the target Task. Without this flag, new activities are created mindlessly in the current Task.
1.2.5 FLAG_ACTIVITY_NEW_TASK in taskAffinity (2)
In 1.2.4, you can see that when an Activity starts with FLAG_ACTIVITY_NEW_TASK, if the taskAffinity of the Activity is different from that of the current Task (Task#208), The Activity will then be created in another Task (Task#207) that is identical to the Activity’s taskAffinity.
But I also encountered a special case in practice:
Start a MainActivity that exists in Task#224. Then start DifferentAffintyActivty with FLAG_ACTIVITY_NEW_TASK. This Activity is created in Task#225 because taskAffinity is different from Task#224. Then start SingleTopActivity in Task#225. Although taskAffinity is different from Task#225, However, since FLAG_ACTIVITY_NEW_TASK is not declared when SingleTopActivity is started, the SingleTopActivity is started in Task#225. Then move Task#224 to the foreground:
[0,0] bounds=[0,0] bounds=[0,0][1920,1200] #0 Task= Task type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[1920,1200] #0 ActivityRecord{700b3e2 u0 com.test.launchmodetest/.MainActivity t224} type=standard mode=fullscreen Override-mode =undefined requester-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #5 Task=225 type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #1 ActivityRecord{7cea9f5u0 com.test.launchmodetest/.SingleTopActivity t225} type=standard mode=fullscreen override-mode=undefined Requision-bounds =[0,0][0,0] Bounds =[0,0][1920,1200] #0 ActivityRecord{14A0B22u0 com.test.launchmodetest/.DifferentAffinityActivity t225} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120]Copy the code
Start DifferentAffintyActivty by FLAG_ACTIVITY_NEW_TASK with Task#224’s MainActivity:
Task= Task= Task= Task= Task= Task= Task= Task= Task= Task= Task= Task= Task= Task= Task ActivityRecord{7cea9f5 u0 com.test.launchmodetest/.SingleTopActivity t225} type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] Bounds =[0,0][19201200] #0 ActivityRecord{14A0b22u0 com.test.launchmodetest/.DifferentAffinityActivity t225} type=standard mode=fullscreen override-mode=undefined Requested-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #6 Task=224 type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120] # 0 ActivityRecord {700 b3e2 u0 com. Test. Launchmodetest /. MainActivity T224} type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920 1200]Copy the code
Here you see that Task#225 has been moved entirely from the background to the foreground, but nothing else has changed.
1) Unlike launchMode singleTask, SingleTopActivity on StandardActivityz is not destroyed. This startup simply brings StandardActivity to the foreground of Task#225, and does not change the Activity within Task#225.
2) According to 1.2.4, an instance of DifferentAffintyActivty should be created again in Task#225, but the fact is that Task#225 just moves from the background to the foreground without any new instance being created. The reason for this, following the code, is that the newly launched DifferentAffintyActivty is a realActivity for Task#225, The new StandardActivity in 1.2.4 is not the realActivity of Task#207, so 1.2.4 and 1.2.5 go through a different process and end up not being created again in Task#225. StandardActivity is created again in Task#207.
As you can see here, there are too many factors to consider in the process of launching an Activity to rely on taskAffinity, launchMode, and Intent flags alone.
2 FLAG_ACTIVITY_SINGLE_TOP
2.1 FLAG_ACTIVITY_SINGLE_TOP definition
/**
* If set, the activity will not be launched if it is already running
* at the top of the history stack. See
* <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html#TaskLaunchModes"> * Tasks and Back Stack</a> for more information. * /
public static final int FLAG_ACTIVITY_SINGLE_TOP = 0x20000000;
Copy the code
1), slag turn:
With this flag set, the Activity will not be restarted if it is already running on top of the current Task.
2) Google Docs:
FLAG_ACTIVITY_SINGLE_TOP
If the Activity to be started is the current Activity (that is, the Activity at the top of the return stack), the existing instance receives a call to onNewIntent() and does not create a new instance of the Activity. This is the same behavior as the “singleTop” launchMode value.
2.2 FLAG_ACTIVITY_SINGLE_TOP Actual application
FLAG_ACTIVITY_SINGLE_TOP is added to the Intent each time StandardActivity is launched, and StandardActivity’s launchMode is declared as Standard.
2.2.1 StandardActivity instance already in Task Top tries to start another new instance
Start StandardActivity with MainActivity as a starting point:
Task= Task type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #1 Task= Task type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] [1920,1200] #1 ActivityRecord{3d834ae u0 com.test.launchmode/.StandardActivity t125} type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] Bounds =[0,0][1920,1200] #0 ActivityRecord{a6de54bu0 com.test.launchmode/.MainActivity t125} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120]Copy the code
Start StandardActivity again as FLAG_ACTIVITY_SINGLE_TOP:
Since there is already an instance of StandardActivity at the top of the current Task, a new StandardActivity will not be started, Instead, the StandardActivity instance at Task Top receives the activity.onnewintent callback:
03-02 14:30:31.116 1490 31702 I wm_new_intent: [0645091, 0125, com. Test. Launchmode /. StandardActivity, NULL, NULL, NULL, 536870912] 14:30:31. 03-02, 123, 4100, 4100 I wm_on_top_resumed_lost_called: [64500910, com. Test. The launchmode. StandardActivity, pausing] 14:30:31. 03-02, 125, 4100, 4100 I wm_on_paused_called: [64500910, com. Test. The launchmode. StandardActivity, performPause] 14:30:31. 03-02, 125, 4100, 4100 I launchmode_test: StandardActivity#onNewIntent 03-02 14:30:31.126 4100 4100 I wm_on_resume_called: [64500910, com. Test. The launchmode. StandardActivity, LIFECYCLER_RESUME_ACTIVITY] 14:30:31. 03-02, 127, 4100, 4100 I wm_on_top_resumed_gained_called: [64500910,com.test.launchmode.StandardActivity,topWhenResuming]Copy the code
2.2.2 The StandardActivity instance tries to start another new instance without being in Task Top
Start a SingleTopActivity after 2.2.1:
Task= Task type=standard mode=fullscreen overrider-mode =undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #2 Task= Task type=standard mode=fullscreen overrider-mode =undefined bounds=[0,0][0,0] [1920,1200] #2 ActivityRecord{9bd59d0 u0 com.test.launchmode/.SingleTopActivity t125} type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #1 ActivityRecord{3d834ae u0 com.test.launchmode/.StandardActivity t125} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120] # 0 ActivityRecord {a6de54b u0 com. Test. The launchmode /. MainActivity t125} Type =standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200]Copy the code
Now StandardActivity is not top, try again to start StandardActivity:
Task= Task type=standard mode=fullscreen overrider-mode =undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #3 Task= Task type=standard mode=fullscreen overrider-mode =undefined bounds=[0,0][0,0] [1920,1200] #3 ActivityRecord{1f5c973 u0 com.test.launchmode/.StandardActivity t125} type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #2 ActivityRecord{9bd59d0u0 com.test.launchmode/.SingleTopActivity t125} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120] # 1 ActivityRecord {3 d834ae u0 com. Test. The launchmode /. StandardActivity T125} type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #0 ActivityRecord{a6de54b u0 com.test.launchmode/.MainActivity t125} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120]Copy the code
Since StandardActivity1, the instance of StandardActivity started earlier, is not at top, a new instance of SingleTopActivity, StandardActivity2, will be created this time.
Same as launchModo set to “singleTop”.
3 FLAG_ACTIVITY_CLEAR_TOP
3.1 FLAG_ACTIVITY_CLEAR_TOP definition
/** * If set, and the activity being launched is already running in the * current task, then instead of launching a new instance of that activity, * all of the other activities on top of it will be closed and this Intent * will be delivered to the (now on top) old activity as a new Intent. * * <p>For example, consider a task consisting of the activities: A, B, C, D. * If D calls startActivity() with an Intent that resolves to the component * of activity B, then C and D will be finished and B receive the given * Intent, resulting in the stack now being: A, B. * * <p>The currently running instance of activity B in the above example will * either receive the new intent you are starting here in its * onNewIntent() method, or be itself finished and restarted with the * new intent. If it has declared its launch mode to be "multiple" (the * default) and you have not set {@link #FLAG_ACTIVITY_SINGLE_TOP} in
* the same intent, then it will be finished and re-created; for all other
* launch modes or if {@link #FLAG_ACTIVITY_SINGLE_TOP} is set then this
* Intent will be delivered to the current instance's onNewIntent().
*
* <p>This launch mode can also be used to good effect in conjunction with
* {@link #FLAG_ACTIVITY_NEW_TASK}: if used to start the root activity
* of a task, it will bring any currently running instance of that task
* to the foreground, and then clear it to its root state. This is
* especially useful, for example, when launching an activity from the
* notification manager.
*
* <p>See
* <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back
* Stack</a> for more information about tasks.
*/
public static final int FLAG_ACTIVITY_CLEAR_TOP = 0x04000000;
Copy the code
1), slag turn: In the case of this flag setting, if the Activity to be started is already running in the current Task, all other activities on that Activity are destroyed, and the Intent is delivered to the (now top) old Activity as the new Intent. Instead of starting a new instance of the Activity.
For example, A Task now contains four activities: A, B, C, and D. If D calls startActivity to start B, C and D are destroyed, and B receives the given Intent. As A result, the stack is now A, B.
In the example above, the currently running instance of Activity B either receives the new Intent you launched in its onNewIntent() method or is destroyed and restarts with the new Intent itself. If it already declares its launch mode to be “multiple” (the default) and you don’t set FLAG_ACTIVITY_SINGLE_TOP in the same Intent, it will be destroyed and recreated. For all other launch modes, or if FLAG_ACTIVITY_SINGLE_TOP is set, the Intent is sent to the current instance’s onNewIntent().
This startup mode also works well with FLAG_ACTIVITY_NEW_TASK: if used to start a Task’s root Activity, it brings the running instance of the Task to the foreground and then clears it to the root state. This is especially useful, for example, when starting an Activity from NotificationManager.
2) Google Docs:
FLAG_ACTIVITY_CLEAR_TOP
If the Activity you want to start is already running in the current Task, a new instance of the Activity is not started, but all other activities on top of it are destroyed. And passes the intent to its recovered instance (now at the top of the stack) via onNewIntent().
The launchMode property does not have a value to generate this behavior.
FLAG_ACTIVITY_CLEAR_TOP is most often used in conjunction with FLAG_ACTIVITY_NEW_TASK. Using these two tags together, you can find existing activities in other tasks and place them in a position to respond to intEnts.
Note: If you specify that the Activity starts in “Standard” mode, the system will also remove it from the stack and start a new instance in its place to handle the incoming intent. This is because when the launch mode is “Standard”, a new instance is always created for a new intent.
3.2 FLAG_ACTIVITY_CLEAR_TOP Actual application
FLAG_ACTIVITY_CLEAR_TOP is added to the Intent each time the MainActivity of the test App is launched.
3.2.1 The launchMode of MainActivity is standard
Start a new StandardActivity on the MainActivity interface:
Task= Task type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #1 Task= Task type=standard mode=fullscreen override-mode=undefined bounds=[0,0][0,0] [1920,1200] #1 ActivityRecord{28de46f u0 com.test.launchmode/.StandardActivity t128} type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #0 ActivityRecord{1ad7ad0 u0 com.test.launchmode/.MainActivity t128} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120]Copy the code
Start MainActivity with StandardActivity and FLAG_ACTIVITY_CLEAR_TOP in the Intent:
Task= Task type=standard mode=fullscreen override-mode=undefined requester-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #0 ActivityRecord{aceb047 u0 com.test.launchmode/.MainActivity t128} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120]Copy the code
The StandardActivity created earlier was destroyed, the MainActivity instance MainActivity1 was destroyed anda new instance MainActivity2 was created:
03-02 15:17:46.728 1490 5553 I wM_finish_activity: [0428348, 7128, com. Test. Launchmode /. StandardActivity, clear - a task - stack] 15:17:46. 03-02, 731, 1490, 5553 I wm_pause_activity: [0428348 7, com. Test. Launchmode /. StandardActivity, userLeaving = false, finish] 15:17:46. 03-02, 732, 1490, 5553 I wm_finish_activity: [0281638, 4128, com. Test. Launchmode /. MainActivity, clear - a task - top] 15:17:46. 03-02, 733, 1490, 5553 I wm_destroy_activity: [0281638, 4128, com. Test. Launchmode /. MainActivity, finish - imm: finishIfPossible] 15:17:46. 03-02, 743, 1490, 5553 I Wm_task_moved: [128,1,6] 03-02 15:17:46.743 1490 5553 I wm_create_activity: [0181177, 03128, com. Test. Launchmode /. MainActivity, NULL, NULL, NULL, 67108864] 15:17:46. 03-02, 759, 6189, 6189 I wm_on_top_resumed_lost_called: [42853487, com. Test. The launchmode. StandardActivity, topStateChangedWhenResumed] 15:17:46. 03-02, 763, 6189, 6189 I wm_on_paused_called: [42853487, com. Test. The launchmode. StandardActivity, performPause] 15:17:46. 03-02, 764, 1490, 5553 I wm_add_to_stopping: [0428348 7, com. Test. Launchmode /. StandardActivity, completeFinishing] 15:17:46. 03-02, 770, 1490, 5553 I wm_restart_activity: [0181177, 03128, com. Test. Launchmode /. MainActivity] 15:17:46. 03-02, 772, 1490, 5553 I wm_set_resumed_activity: [0, com. Test. Launchmode /. MainActivity, minimalResumeActivityLocked] 15:17:46. 03-02, 778, 6189, 6189 I wm_on_destroy_called: [28146384, com. Test. The launchmode. MainActivity, performDestroy] 15:17:46. 03-02, 816, 6189, 6189 I launchmode_test: MainActivity#onCreate 03-02 15:17:46.869 6189 6189 I wm_on_create_called: [181317703, com. Test. The launchmode. MainActivity, performCreate] 15:17:46. 03-02, 872, 6189, 6189 I wm_on_start_called: [181317703, com. Test. The launchmode. MainActivity, handleStartActivity] 15:17:46. 03-02, 873, 6189, 6189 I wm_on_resume_called: [181317703, com. Test. The launchmode. MainActivity, RESUME_ACTIVITY] 15:17:46. 03-02, 896, 6189, 6189 I wm_on_top_resumed_gained_called: [181317703, com. Test. The launchmode. MainActivity, topStateChangedWhenResumed] 15:17:47. 03-02, 016, 1490, 1512 I wm_activity_launch_time: [0181177-03, com. Test. Launchmode /. MainActivity, 294] 15:17:47. 03-02, 230, 1490, 1515 I wm_destroy_activity: [0428348, 7128, com. Test. Launchmode /. StandardActivity, finish - imm: idle] 15:17:47. 03-02, 349, 6189, 6189 I wm_on_stop_called: [42853487, com. Test. The launchmode. StandardActivity, LIFECYCLER_STOP_ACTIVITY] 15:17:47. 03-02, 353, 6189, 6189 I wm_on_destroy_called: [42853487,com.test.launchmode.StandardActivity,performDestroy]Copy the code
3.2.2 The launchMode of MainActivity is singleTop
Check whether the launchMode of MainActivity is not the default standard and whether it is consistent with the behavior described in the definition, that is, whether the MainActivity will not be destroyed and rebuilt. Therefore, set the launchMode of MainActivity to singleTop.
Start a new StandardActivity on the MainActivity interface:
Task= Task type=standard mode=fullscreen overrider-mode =undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #1 Task= Task type=standard mode=fullscreen overrider-mode =undefined bounds=[0,0][0,0] [1920,1200] #1 ActivityRecord{c383fe3 u0 com.test.launchmode/.StandardActivity t130} type=standard mode=fullscreen Override-mode =undefined requision-bounds =[0,0][0,0] bounds=[0,0][1920,1200] #0 ActivityRecord{19f7db4u0 com.test.launchmode/.MainActivity t130} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120]Copy the code
Start MainActivity with StandardActivity and FLAG_ACTIVITY_CLEAR_TOP in the Intent:
Task= Task type=standard mode=fullscreen overrider-mode =undefined bounds=[0,0][0,0] bounds=[0,0][1920,1200] #0 Task= Task type=standard mode=fullscreen overrider-mode =undefined bounds=[0,0][0,0] [1920,1200] #0 ActivityRecord{19f7db4 u0 com.test.launchmode/.MainActivity t130} type=standard mode=fullscreen override-mode=undefined Requested - bounds = [0, 0] [0, 0] bounds = [0, 0] [1920120]Copy the code
The StandardActivity created earlier was destroyed, the MainActivity was not destroyed, and the Activity. OnNewIntent callback was received:
03-02 15:24:34.710 1490 9314 I wM_finish_activity: [0205129, 63130, com. Test. Launchmode /. StandardActivity, clear - a task - stack] 15:24:34. 03-02, 712, 1490, 9314 I wm_pause_activity: [0205129, 63, com. Test. Launchmode /. StandardActivity, userLeaving = false, finish] 15:24:34. 03-02, 714, 1490, 9314 I wm_new_intent: [0272962, 0130, com. Test. Launchmode /. MainActivity, android. The intent. The action. The MAIN, NULL, NULL, 270532608] 03-02 15:24:34. 715 1490 9314 I wm_task_moved: [130,1,6] 03-02 15:24:34.727 6902 6902 I wm_on_top_resumed_lost_called: [205012963, com. Test. The launchmode. StandardActivity, topStateChangedWhenResumed] 15:24:34. 03-02, 728, 6902, 6902 I wm_on_paused_called: [205012963, com. Test. The launchmode. StandardActivity, performPause] 15:24:34. 03-02, 729, 1490, 9314 I wm_add_to_stopping: [0205129, 63, com. Test. Launchmode /. StandardActivity, completeFinishing] 15:24:34. 03-02, 734, 1490, 9314 I wm_set_resumed_activity: [0, com. Test. Launchmode /. MainActivity, resumeTopActivityInnerLocked] 15:24:34. 03-02, 743, 1490, 9314 I wm_resume_activity: [0272962, 0130, com. Test. Launchmode /. MainActivity] 15:24:34. 03-02, 786, 6902, 6902 I wm_on_restart_called: [27229620, com. Test. The launchmode. MainActivity, performRestartActivity] 15:24:34. 03-02, 786, 6902, 6902 I wm_on_start_called: [27229620, com. Test. The launchmode. MainActivity, handleStartActivity] 15:24:34. 03-02, 787, 6902, 6902 I launchmode_test: MainActivity#onNewIntent 03-02 15:24:34.787 6902 6902 I wm_on_resume_called: [27229620, com. Test. The launchmode. MainActivity, RESUME_ACTIVITY] 15:24:34. 03-02, 788, 6902, 6902 I wm_on_top_resumed_gained_called: [27229620, com. Test. The launchmode. MainActivity, topWhenResuming] 15:24:35. 03-02, 227, 1490, 1515 I wm_destroy_activity: [0205129, 63130, com. Test. Launchmode /. StandardActivity, finish - imm: idle] 15:24:35. 03-02, 248, 6902, 6902 I wm_on_stop_called: [205012963, com. Test. The launchmode. StandardActivity, LIFECYCLER_STOP_ACTIVITY] 15:24:35. 03-02, 249, 6902, 6902 I wm_on_destroy_called: [205012963,com.test.launchmode.StandardActivity,performDestroy]Copy the code
Four,
1 launchMode
1.1 standard
Each time an Activity is started, a new instance of the Activity is created in the current Task.
1.2 singleTop
1) If the Activity to be started already has an instance in the top Task, a new instance will not be created.
2) If an instance of the Activity is currently running in a Task but is not at the top of the Task, create a new instance.
1.3 singleTask
1.3.1 The taskAffinity of the Activity to be started is the same as the current Task affinity (default is the App package name)
1) If the Activity to be started is already on top of the Task, no new instance will be created.
If an instance of the Activity is running in the current Task, but it is not on top of the Task, then clear all activities on the Activity.
1.3.2 The taskAffinity of the Activity to be started is different from the current Task affinity (which defaults to the App package name)
If there is no instance of the Activity running in the current Task, create a new Task for the Activity.
2) If a Task in the background is running the Activity, the new instance is not created. Instead, the Task is moved to the foreground and all activities on top of the Activity are removed from the Task.
1.4 singleInstance
If there are any tasks running the Activity, move that Task to the foreground; otherwise, new tasks are always created for the newly started Activity, and only one Activity can be in that Task.
1.5 SingleInstancePerTask
The default is similar to singleTask, except that singleInstancePerTask does not require a different taskAffinity to create a new Task.
Intent.flag_activity_multiple_task intent.flag_activity_new_document Each time you start an Activity with launchMode set to “singleInstancePerTask”, you can create a new Task. The newly launched Activity is the root Activity of the newly created Task.
1.6 Summary again
To put it bluntly, standard, singleTop, singleTask, and SingleInstance require a progressively higher number of Activity instances:
Standard: You can create an unlimited number of Activity instances.
SingleTop: If the top of the current Task is already the Activity being started, then do not start it again.
SingleTask: There can only be one Activity that is the root Activity of the Task it is running on (different cases for taskAffinity).
SingleInstance: This Activity can have only one Activity, and its Task can have only one Activity.
SingleInstancePerTask: Is an extension of singleTask. This Activity can have multiple instances, but each is the root Activity of its Task.
2 Intent flag
2.1 FLAG_ACTIVITY_NEW_TASK
If FLAG_ACTIVITY_NEW_TASK is involved, taskAffinity should be taken into account when starting an Activity, which affects whether the Activity is started in the current Task or in a new Task. According to the previous analysis, the function of this flag is actually different from that of launchMode as “singleTask”, which is quite complex.
2.2 FLAG_ACTIVITY_SINGLE_TOP
The launchMode function is the same as “singleTop”.
2.3 FLAG_ACTIVITY_CLEAR_TOP
If the Activity is currently running in Task, clear all other activities on top of it.
Depending on the launchMode of the Activity being launched and the flag of the Intent being launched, the existing Activity may also be destroyed and rebuilt.