Android 阅读Tasks and Back Stack文章后的重点摘抄
这篇文章是做android的必读篇目,要仔细阅读,原文连接http://developer.android.com/guide/components/tasks-and-back-stack.html
另外一篇 http://developer.android.com/guide/topics/manifest/activity-element.html#clear
先看一看task和back stack的定义:
A task is a collection of activities that users interact with when performing a certain job. The activities are arranged in a stack (the "back stack"), in the order in which each activity is opened.
1.
Activities in the stack are never rearranged, only pushed and popped from the stack—pushed onto the stack when started by the current activity and popped off when the user leaves it using the Back button.
注意这句,明确指出activity是不能重新调整顺序的,比如,有一个task中有a ,b ,c 我想通过intent等方法把stack底的a实例移到最上边现实出来,这样的功能是实现不了的!这样的需求应该通过其他方法解决,比如再建立一个a实例。
2
A task is a cohesive unit that can move to the "background" when users begin a new task or go to the Home screen, via theHome button. While in the background, all the activities in the task are stopped, but the back stack for the task remains intact—the task has simply lost focus while another task takes place。
back stack 保存了task中的所有activity,当新task启动后,原有task的整个back stack会被移入后台。
3.
However, you might decide that you want to interrupt the normal behavior.
Perhaps you want an activity in your application to begin a new task when it is started (instead of being placed within the current task);
or, when you start an activity, you want to bring forward an existing instance of it (instead of creating a new instance on top of the back stack);
or, you want your back stack to be cleared of all activities except for the root activity when the user leaves the task.
You can do these things and more, with attributes in the <activity>
manifest element and with flags in the intent that you pass to startActivity()
.
In this regard, the principal <activity>
attributes you can use are:
taskAffinity
launchMode
allowTaskReparenting
clearTaskOnLaunch
alwaysRetainTaskState
finishOnTaskLaunch
And the principal intent flags you can use are:
4.一下内容十分重要,也比较长,要耐心仔细阅读
Defining launch modes
Launch modes allow you to define how a new instance of an activity is associated with the current task. You can define different launch modes in two ways:
- Using the manifest file
When you declare an activity in your manifest file, you can specify how the activity should associate with tasks when it starts.
- Using Intent flags
When you call
startActivity()
, you can include a flag in theIntent
that declares how (or whether) the new activity should associate with the current task.
这里需要注意,提到的这2种方式仅仅影响launch mode,还有许多task调整相关的方法不与上面这2个东西相关,比如 android:clearTaskOnLaunch,请参看 http://developer.android.com/guide/topics/manifest/activity-element.html#clear
As such, if Activity A starts Activity B, Activity B can define in its manifest how it should associate with the current task (if at all) and Activity A can also request how Activity B should associate with current task. If both activities define how Activity B should associate with a task, then Activity A's request (as defined in the intent) is honored over Activity B's request (as defined in its manifest).
注意这里,如果同时通过intent 和 launch mode 定义启动方式,会以intent的为准。如果不冲突的话,会取交集吗?
Note: Some launch modes available for the manifest file are not available as flags for an intent and, likewise, some launch modes available as flags for an intent cannot be defined in the manifest.
这里说的是,launch modes 和intent 都有独特的启动方式,互相是不包涵的。
Using the manifest file
When declaring an activity in your manifest file, you can specify how the activity should associate with a task using the <activity>
element's launchMode
attribute.
The launchMode
attribute specifies an instruction on how the activity should be launched into a task. There are four different launch modes you can assign to the launchMode
attribute:
"standard"
(the default mode)- Default. The system creates a new instance of the activity in the task from which it was started and routes the intent to it. The activity can be instantiated multiple times, each instance can belong to different tasks, and one task can have multiple instances.
"singleTop" 在task顶端保持唯一,在系统中可有多个实例
- If an instance of the activity already exists at the top of the current task, the system routes the intent to that instance through a call to its
onNewIntent()
method, rather than creating a new instance of the activity. The activity can be instantiated multiple times, each instance can belong to different tasks, and one task can have multiple instances (but only if the activity at the top of the back stack is not an existing instance of the activity).For example, suppose a task's back stack consists of root activity A with activities B, C, and D on top (the stack is A-B-C-D; D is on top). An intent arrives for an activity of type D. If D has the default
"standard"
launch mode, a new instance of the class is launched and the stack becomes A-B-C-D-D. However, if D's launch mode is"singleTop"
, the existing instance of D receives the intent throughonNewIntent()
, because it's at the top of the stack—the stack remains A-B-C-D. However, if an intent arrives for an activity of type B, then a new instance of B is added to the stack, even if its launch mode is"singleTop"
.singleTop 可以保持只存在一个activity实例,但是是有要求的,就是这个activity必须在当前task的顶部!如果不在就会创建新的实例。应用场合如下:不想出现2个同样的activity在顶部。比如用户正在一个activity阅读信息,这时来了notification,用户点击后应该更新这些信息,而不是新建一个activity,这样在点击back时,就不会出现回到旧信息activity的情况了。这种情况正是下面这段英语提到的。
Note: When a new instance of an activity is created, the user can press the Back button to return to the previous activity. But when an existing instance of an activity handles a new intent, the user cannot press the Back button to return to the state of the activity before the new intent arrived in
onNewIntent()
. "singleTask" 在系统中保持唯一实例
- The system creates a new task and instantiates the activity at the root of the new task. However, if an instance of the activity already exists in a separate task, the system routes the intent to the existing instance through a call to its
onNewIntent()
method, rather than creating a new instance. Only one instance of the activity can exist at a time. - 有实例存在就跳转到该实例,没有实例存在就会创建新的task,并把实例放在root。这里需要注意的是,有实例存在的情况,如果这个实例不在task的顶端,那么不会自动把它置顶,参看下面的FLAG_ACTIVITY_NEW_TASK。
-
Note: Although the activity starts in a new task, the Back button still returns the user to the previous activity.
"singleInstance"
. 在系统中保持唯一实例,并且单独存在一个task中- Same as
"singleTask"
, except that the system doesn't launch any other activities into the task holding the instance. The activity is always the single and only member of its task; any activities started by this one open in a separate task. - 关于这4种的区别,请参看http://developer.android.com/guide/topics/manifest/activity-element.html#clear如果你不喜欢英文,请参看http://blog.csdn.net/guomeijuan916/article/details/8121468
As another example, the Android Browser application declares that the web browser activity should always open in its own task—by specifying the singleTask
launch mode in the <activity>
element. This means that if your application issues an intent to open the Android Browser, its activity is not placed in the same task as your application. Instead, either a new task starts for the Browser or, if the Browser already has a task running in the background, that task is brought forward to handle the new intent.
Regardless of whether an activity starts in a new task or in the same task as the activity that started it, the Backbutton always takes the user to the previous activity. However, if you start an activity that specifies thesingleTask
launch mode, then if an instance of that activity exists in a background task, that whole task is brought to the foreground. At this point, the back stack now includes all activities from the task brought forward, at the top of the stack. Figure 4 illustrates this type of scenario.
注意,整个task都被移动到了前台,包括activity x! 不过activity x 和activity y的这个task是如何生成的呢?activity y作为singleTask类型,不是应该在task的root吗?为什么这里它不在root上呢?怎么做到的?如果activity x在上方又会怎么样?系统会自动把activity x弹出去舍弃吗?
Figure 4. A representation of how an activity with launch mode "singleTask" is added to the back stack. If the activity is already a part of a background task with its own back stack, then the entire back stack also comes forward, on top of the current task.
For more information about using launch modes in the manifest file, see the <activity>
element documentation, where the launchMode
attribute and the accepted values are discussed more.
Note: The behaviors that you specify for your activity with the launchMode
attribute can be overridden by flags included with the intent that start your activity, as discussed in the next section.
Using Intent flags
When starting an activity, you can modify the default association of an activity to its task by including flags in the intent that you deliver to startActivity()
. The flags you can use to modify the default behavior are:
FLAG_ACTIVITY_NEW_TASK
Start the activity in a new task. If a task is already running for the activity you are now starting, that task is brought to the foreground with its last state restored and the activity receives the new intent inonNewIntent()
.
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.
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.
根据这里所说的,放到前台的是整个task,该activity会收到onNewIntent()信息,但是不会把这个activity放到task的顶端,如果需要同时现实该activity,那么应该和FLAG_ACTIVITY_CLEAR_TOP一起使用!
This produces the same behavior as the "singleTask"
launchMode
value, discussed in the previous section.
FLAG_ACTIVITY_SINGLE_TOP
If the activity being started is the current activity (at the top of the back stack), then the existing instance receives a call to onNewIntent()
, instead of creating a new instance of the activity.
This produces the same behavior as the "singleTop"
launchMode
value, discussed in the previous section.
FLAG_ACTIVITY_CLEAR_TOP
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.
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.
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 FLAG_ACTIVITY_SINGLE_TOP in the same intent, then it will be finished and re-created; for all other launch modes or if FLAG_ACTIVITY_SINGLE_TOP is set then this Intent will be delivered to the current instance's onNewIntent().
This launch mode can also be used to good effect in conjunction with 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.
注意上面说说的,clear_top这个标志位不一定会调用 onNewIntent(), 只有同时使用 FLAG_ACTIVITY_SINGLE_TOP,才会调用onNewIntent(),不然,会先finish本身,再创建一个新的!!
There is no value for the launchMode
attribute that produces this behavior.
FLAG_ACTIVITY_CLEAR_TOP
is most often used in conjunction with FLAG_ACTIVITY_NEW_TASK
. When used together, these flags are a way of locating an existing activity in another task and putting it in a position where it can respond to the intent.
Note: If the launch mode of the designated activity is "standard"
, it too is removed from the stack and a new instance is launched in its place to handle the incoming intent. That's because a new instance is always created for a new intent when the launch mode is "standard"
.
android:launchMode
An instruction on how the activity should be launched. There are four modes that work in conjunction with activity flags (FLAG_ACTIVITY_*
constants) in Intent
objects to determine what should happen when the activity is called upon to handle an intent. They are:
"standard
"
"singleTop
"
"singleTask
"
"singleInstance
"
The default mode is "standard
".
As shown in the table below, the modes fall into two main groups, with "standard
" and "singleTop
" activities on one side, and "singleTask
" and "singleInstance
" activities on the other. An activity with the "standard
" or "singleTop
" launch mode can be instantiated multiple times. The instances can belong to any task and can be located anywhere in the activity stack. Typically, they're launched into the task that called
(unless the Intent object contains astartActivity()
instruction, in which case a different task is chosen — see the taskAffinityattribute).FLAG_ACTIVITY_NEW_TASK
In contrast, "singleTask
" and "singleInstance
" activities can only begin a task. They are always at the root of the activity stack. Moreover, the device can hold only one instance of the activity at a time — only one such task.
The "standard
" and "singleTop
" modes differ from each other in just one respect: Every time there's a new intent for a "standard
" activity, a new instance of the class is created to respond to that intent. Each instance handles a single intent. Similarly, a new instance of a "singleTop
" activity may also be created to handle a new intent. However, if the target task already has an existing instance of the activity at the top of its stack, that instance will receive the new intent (in an
call); a new instance is not created. In other circumstances — for example, if an existing instance of the "onNewIntent()
singleTop
" activity is in the target task, but not at the top of the stack, or if it's at the top of a stack, but not in the target task — a new instance would be created and pushed on the stack.
The "singleTask
" and "singleInstance
" modes also differ from each other in only one respect: A "singleTask
" activity allows other activities to be part of its task. It's always at the root of its task, but other activities (necessarily "standard
" and "singleTop
" activities) can be launched into that task. A "singleInstance
" activity, on the other hand, permits no other activities to be part of its task. It's the only activity in the task. If it starts another activity, that activity is assigned to a different task — as if FLAG_ACTIVITY_NEW_TASK
was in the intent.
Use Cases | Launch Mode | Multiple Instances? | Comments |
---|---|---|---|
Normal launches for most activities | "standard " |
Yes | Default. The system always creates a new instance of the activity in the target task and routes the intent to it. |
"singleTop " |
Conditionally | If an instance of the activity already exists at the top of the target task, the system routes the intent to that instance through a call to itsonNewIntent() method, rather than creating a new instance of the activity. |
|
Specialized launches (not recommended for general use) |
"singleTask " |
No | The system creates the activity at the root of a new task and routes the intent to it. However, if an instance of the activity already exists, the system routes the intent to existing instance through a call to itsonNewIntent() method, rather than creating a new one. |
"singleInstance " |
No | Same as "singleTask" , except that the system doesn't launch any other activities into the task holding the instance. The activity is always the single and only member of its task. |
As shown in the table above, standard
is the default mode and is appropriate for most types of activities. SingleTop
is also a common and useful launch mode for many types of activities. The other modes — singleTask
and singleInstance
— are not appropriate for most applications, since they result in an interaction model that is likely to be unfamiliar to users and is very different from most other applications.
Regardless of the launch mode that you choose, make sure to test the usability of the activity during launch and when navigating back to it from other activities and tasks using the Back button.