Tasks and Back Stack

来源:互联网 发布:网络祭奠 编辑:程序博客网 时间:2024/05/21 09:29
Activities >

Tasks and Back Stack

任务和栈

Quickview

  • All activities belong to a task
  • A task contains a collection of activities in the order in which the user interacts with them
  • Tasks can move to the background and retain the state of each activity in order for the user to perform other tasks without loosing their work

In this document

  1. Saving Activity State
  2. Managing Tasks
    1. Defining launch modes
    2. Handling affinities
    3. Clearing the back stack
    4. Starting a task

See also

  1. Application Lifecycle video
  2. <activity> manifest element

An application usually contains multiple activities. Each activity should be designed around a specific kind of action the user can perform and can start other activities. For example, an email application might have one activity to show a list of new email. When the user selects an email, a new activity opens to view that email.

一个应用通常会包含很多个activity。每个activity应该围绕着两个目标设计:让用户完成某个特定类型的行为,并可以开启别的activity。比如,一个Email应用可能会有一个activity来显示新email的列表。当用户选中某个email,一个新的activity将打开,去查看这个email。

An activity can even start activities that exist in other applications on the device. For example, if your application wants to send an email, you can define an intent to perform a "send" action and include some data, such as an email address and a message. An activity from another application that declares itself to handle this kind of intent then opens. In this case, the intent is to send an email, so an email application's "compose" activity starts (if multiple activities support the same intent, then the system lets the user select which one to use). When the email is sent, your activity resumes and it seems as if the email activity was part of your application. Even though the activities may be from different applications, Android maintains this seamless user experience by keeping both activities in the sametask.

一个activity甚至可以开启设备上存在于别的应用中的activity。比如,如果你的应用想要发送一封邮件,你可以生成一个  能完成一个“发送”动作的意图,在意图中可以在包含些数据,比如email地址和信息。别的应用的某个activity,如果声明过它可以处理这种意图,那它将会打开。在这个例子中,意图是发送一封邮件,所以一个邮件应用的相关activity启动(如果很多个activity都支持这个意图,那么系统会让用户选择使用哪个activity)。(译者注:比如你发起一个上网的意图,而浏览器有很多个,那么系统就会让你选择启动哪个浏览器)。当email发送完后,你的activity恢复运行。从整体来看,那个email activity就像是你的程序的一部分。尽管activity也许来自与不同的应用,Android通过将这两个activity放在相同的任务里,来实现这种无缝的用户体验。

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.

一个任务是用户为完成某个特定的工作,与之交互的activity的集合。这些activity被安排在一个堆栈里,以每个activity被打开的顺序排列。

The device Home screen is the starting place for most tasks. When the user touches an icon in the application launcher (or a shortcut on the Home screen), that application's task comes to the foreground. If no task exists for the application (the application has not been used recently), then a new task is created and the "main" activity for that application opens as the root activity in the stack.

设备的Home屏,是大多数任务的开始之地。当用户触摸了应用管理器的某个图标(或者Home屏的某个快捷方式),那个图标对应的应用的任务就开始在前台运行。如果那个应用没有对应的任务存在(应用最近没有被使用),那么一个新的任务就会被创建,那个应用的“main” activity启动,并作为堆栈里的根activity。

When the current activity starts another, the new activity is pushed on the top of the stack and takes focus. The previous activity remains in the stack, but is stopped. When an activity stops, the system retains the current state of its user interface. When the user presses the BACK key, the current activity is popped from the top of the stack (the activity is destroyed) and the previous activity resumes (the previous state of its UI is restored). 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 key. As such, the back stack operates as a "last in, first out" object structure. Figure 1 visualizes this behavior with a timeline showing the progress between activities along with the current back stack at each point in time.

当前的activity启动了另一个activity时,新activity被压入堆栈顶,并获得焦点。先前的activity仍然在堆栈里,但处于停止状态。当一个activity停止,系统仍然保留着它的用户界面的状态信息。然后用户按下BACK键时,当前activity从栈顶弹出(此activity就被销毁),先前的activity恢复运行(它被保存的用户界面状态信息就恢复了)。在堆栈里的所有activity绝不会重排位置,只会压入栈顶或从栈顶弹出——当从当前activity启动时,新activity压入栈顶;当用户使用BACK键离开当前activity,此activity从栈顶弹出。整体来说,栈的行为如同“后进先出”的数据结构。图1描述了这种行为。



Figure 1. A representation of how each new activity in a task adds an item to the back stack. When the user presses the BACK key, the current activity is destroyed and the previous activity resumes.

If the user continues to press BACK, then each activity in the stack is popped off to reveal the previous one, until the user returns to the Home screen (or to whichever activity was running when the task began). When all activities are removed from the stack, the task no longer exists.

如果用户继续按BACK键,那堆栈里的每个activity一个接一个弹出,并恢复到它之前的状态。直到用户回到了Home屏(或者回到在任务开启之前就在运行的那个activity。译者注:此人逻辑真严密)。当所有activity都弹出后,任务就不存在了。



Figure 2. Two tasks: Task A is in the background, waiting to be resumed, while Task B receives user interaction in the foreground.

Figure 3. A single activity is instantiated multiple times.

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 the HOME key. 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, as shown in figure 2. A task can then return to the "foreground" so users can pick up where they left off. Suppose, for example, that the current task (Task A) has three activities in its stack—two under the current activity. The user presses the HOME key, then starts a new application from the application launcher. When the Home screen appears, Task A goes into the background. When the new application starts, the system starts a task for that application (Task B) with its own stack of activities. After interacting with that application, the user returns Home again and selects the application that originally started Task A. Now, Task A comes to the foreground—all three activities in its stack are intact and the activity at the top of the stack resumes. At this point, the user can also switch back to Task B by going Home and selecting the application icon that started that task (or by touching and holding the HOME key to reveal recent tasks and selecting one). This is an example of multitasking on Android.

当用户开始一个新任务或者使用HOME键回到Home屏,当前任务作为一个整体移动到后台。当处于后台时,它所有的activity被停止,但是这个任务的活动栈仍然是完整无缺的——只是由于另外一个任务的发生,这个任务仅仅是丢失了用户焦点而已。此任务仍然可以回到前台,这样用户可以接着它之前的状态运行它。例如,假设当前任务(任务A)在活动栈里有3个activity——当前activity下有2个activity(译者注:太明显了吧。。)。用户按下Home键,一个新的应用开始,系统为此应用开始一个新的任务(任务B),此任务含有它自己的活动栈。在与这个新应用交互完成后,用户回到Home,选择之前的那个应用来再次启动任务A。现在,任务A来到前台——它栈里的3个activity都很完整,并且此时栈顶的activity恢复运行。同样这个时候,用户也可以切回到任务B,通过回到Home,选择启动任务B的应用图标(或者通过触摸并按住Home键,显示最近的任务,然后选中这个任务)。以上是Android上的一个多任务的例子。

Note: Multiple tasks can be held in the background at once. However, if the user is running many background tasks at the same time, the system might begin destroying background activities in order to recover memory, causing the activity states to be lost. See the following section about Activity state.

注意:后台可以同时维持很多的任务。但是如果用户同一时间运行了太多后台任务,系统也许会销毁后台activity来恢复内存,导致activity状态的丢失。请看下面Activity state部分。

Because the activities in the back stack are never rearranged, if your application allows users to start a particular activity from more than one activity, a new instance of that activity is created and popped onto the stack (rather than bringing any previous instance of the activity to the top). As such, one activity in your application might be instantiated multiple times (even from different tasks), as shown in figure 3. As such, if the user navigates backward using the BACK key, each instance of the activity is revealed in the order they were opened (each with their own UI state). However, you can modify this behavior if you do not want an activity to be instantiated more than once. How to do so is discussed in the later section about Managing Tasks.

由于活动栈里的activity绝不会被重排,如果你的应用允许用户从不止一个activity中启动一个特定的activity,这个activity的一个新实例就会被创建,压入栈顶(而不是将此activity的任何先前生成的实例压入栈顶)。因此,你的应用中的某个activity可能会被实例化很多次(甚至来自不同的任务)。之后,如果用户使用BACK键导航回来,此activity的每个实例依照他们之前生成的顺序一个个恢复(每个都有它自己的UI状态)。但是,如果你不想这个activity被实例化很多次,你可以修改这种行为。怎么做在之后的Managing Tasks部分讨论。

To summarize the default behavior for activities and tasks:

总结下activity和任务的默认行为:

  • When Activity A starts Activity B, Activity A is stopped, but the system retains its state (such as scroll position and text entered into forms). If the user presses the BACK key while in Activity B, Activity A resumes with its state restored.
  • 当Activity A启动Activity B,Activity A被停止,但是系统保留它的状态(比如滚动条位置,表单中的数据)。如果用户在Activity B中按了BACK键,Activity A就会使用保留的状态信息恢复运行。
  • When the user leaves a task by pressing the HOME key, the current activity is stopped and its task goes into the background. The system retains the state of every activity in the task. If the user later resumes the task by selecting the launcher icon that began the task, the task comes to the foreground and resumes the activity at the top of the stack.
  • 当用户按下Home键离开一个任务时,当前activity被停止,它所在的任务转入后台运行。系统保留下这个任务的所有activity状态信息。如果用户之后点击此任务的图标,想再运行这个任务,那么这个任务就会到前台运行,并且恢复运行它的活动栈的栈顶activity。
  • If the user presses the BACK key, the current activity is popped from the stack and destroyed. The previous activity in the stack is resumed. When an activity is destroyed, the system does not retain the activity's state.
  • 如果用户按了BACK键,当前activity从栈中弹出并被销毁。栈里它之前的那个activity恢复运行。一个activity被销毁了,系统并不会保存它的状态信息。
  • Activities can be instantiated multiple times, even from other tasks.
  • activity可以被实例化很多次,甚至是其他的任务实例化它。

Saving Activity State

保存Activity的状态

As discussed above, the system's default behavior preserves the state of an activity when it is stopped. This way, when users navigate back to a previous activity, its user interface appears the way they left it. However, you can—and should—proactively retain the state of your activities using callback methods, in case the activity is destroyed and must be recreated.

如同上面讨论的,当一个activity被停止,系统默认的行为是保存下它的状态。这样,当用户导航回这个activity时,它的用户界面才能和用户离开它时的界面完全一样。然而,当一个activity被销毁,但又必须要重新创建时,你可以,而且应该预先使用回调函数保存下你的activity的状态。

When the system stops one of your activities (such as when a new activity starts or the task moves to the background), the system might destroy that activity completely if it needs to recover system memory. When this happens, information about the activity state is lost. If this happens, the system still knows that the activity has a place in the back stack, but when the activity is brought to the top of the stack the system must recreate it (rather than resume it). In order to avoid loosing the user's work, you should proactively retain it by implementing theonSaveInstanceState() callback methods in your activity.

当系统停止了你的一个activity(比如在一个新activity启动或者你的任务移到了后台的情况下),系统可能会销毁你的activity,在它需要回收系统内存时。这样你的这个activity的信息就完全丢失了。这种情况下,系统仍然会知道这个activity在活动栈里有它的位置,但是当此activity上移到活动栈的栈顶时,系统只能重新创建它(而不能恢复运行它)。为了避免用户丢失工作,你应该预先保存下它的信息,通过在你的activity里实现onSaveInstanceState()回调函数。

For more information about how to save your activity state, see the Activities document.

Managing Tasks

管理任务

The way Android manages tasks and the back stack, as described above—by placing all activities started in succession in the same task and in a "last in, first out" stack—works great for most applications and you shouldn't have to worry about how your activities are associated with tasks or how they exist in the back stack. 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 activitiesstart an activity except for the root activity when the user leaves the task.

如同上面所说,Android管理任务和活动栈的方式,是——将同一个任务里的所有activity按启动的顺序放在一个”后进,先出“的活动栈里——在绝大多数应用里,这个机制都很管用。所以你不需要担心你的activity是怎么和任务关联起来的,或者它们在活动栈里是怎么样的。但也许你就是想要打断这种正常的行为。也许你想要你的应用中的一个activity在启动时开始一个新的任务(而不是它被放置入当前的任务中);或者当你想开始一个activity,你想将它的一个已经存在的实例从后台拿到前台来运行(而不是想创建它的一个新的实例);或者,你想将你的活动栈清空到只剩根activity,当用户离开这个任务的时候。

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().

你可以做到这些,甚至更多,通过使用manifest里的<activity>元素的属性,以及你想要传递给startActivity()的intent 的标志,来实现。

In this regard, the the principal <activity> attributes you can use are:

这种情况下,你可以使用的<activity>重要的属性有:

  • taskAffinity
  • launchMode
  • allowTaskReparenting
  • clearTaskOnLaunch
  • alwaysRetainTaskState
  • finishOnTaskLaunch

And the principal intent flags you can use are:

以及你可以使用的intent重要的标志有:

  • FLAG_ACTIVITY_NEW_TASK
  • FLAG_ACTIVITY_CLEAR_TOP
  • FLAG_ACTIVITY_SINGLE_TOP

In the following sections, you'll see how you can use these manifest attributes and intent flags to define how activities are associated with tasks and how the behave in the back stack.

在下面的章节,你将看到如何使用这些manifest属性以及intent标志,来决定activtiy怎样和任务相关联,以及activity在活动栈里的行为。

Caution: Most applications should not interrupt the default behavior for activities and tasks. If you determine that it's necessary for your activity to modify the default behaviors, use caution and be sure to test the usability of the activity during launch and when navigating back to it from other activities and tasks with the BACK key. Be sure to test for navigation behaviors that might conflict with the user's expected behavior.

警告:绝大多数应用不应该中断activitiy和task的默认行为。你如果确定修改默认的行为是必须的,使用警告标志,以及多做测试来保证activity正常可用,不管是在运行时,或是使用BACK键从别的任务和活动里导航回这个activity时。确保一定要为与预期用户行为不一致的导航行为做测试。

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:

运行模式允许你来决定一个activity的新实例是怎样和当前任务相关联的。指定运行模式,有以下两种方式:

  • 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.

    当你在你的manifest文件里声明了一个activity时,你可以指定这个activity在启动时,和任务相关联的方式。


  • Using Intent flags

    When you call startActivity(), you can include a flag in the Intent that declares how (or whether) the new activity should associate with the current task.

    当你调用startActivity()时,你可以在intent里包含一个标志位,指示这个新activity怎样与当前的任务相关联。

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).

如果Activity A开启Activity B,Activity B可以在它的manifest文件里指定它和当前任务怎样关联,而Activity  A同样也可以要求Activity B怎样与当前任务相关联。如果它们两都指定了Activity B如何与当前任务相关联,那么Activity A的请求(比如定义在intent里)就传递给Activity B了(比如定义在manifest里)。

Note: Some the launch modes available in the manifest 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.

注意:有时manifest的模式可用,但intent的标志位这种模式却不可用。反过来也有这种情况。

Using the manifest file

使用manifest文件

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.

当在你的manifest文件里声明一个activiyt时,你可以使用<activity>元素的launchMode属性来指定这个activity与任务相关联的方式。

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:

launchMode属性说明了一个activity应该怎么样进入到任务里运行。launchMode的属性值有4种类型:

"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.
默认类型。系统在某个activity之前启动过的任务里,创建activity的一个新实例。activity可以实例化很多次,每个实例可以属于不同的任务,一个任务也可以有很多个实例。
"singleTop"
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 the activity at the top of the back stack is not an existing instance of the activity).
如果activity的一个实例已经在当前任务的栈顶存在,系统将向这个实例传递一个intent,调用它的onNewIntent()方法,而不是创建此activity的一个新实例。activity可以被实例化很多次,每个实例可以属于不同的任务,每个任务也可以有很多个实例(但是只能在一种情况下:任务的栈顶的那个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 is deliverd the intent through onNewIntent(), 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".

比如,假设一个任务的活动栈由根activity A以及其他3个activity  B、C和D组成(栈是A-B-C-D,D在栈顶)。现在收到一个想启动activity D的intent,如果D是默认的运行模式,D类的一个新实例就运行了,栈就变为A-B-C-D-D了。但是,如果D的运行模式是”singleTop“,intent就会传递给栈顶的那个已经存在的D实例,通过onNewIntent()方法。因为它在栈顶,而之后栈的形状仍然是A-B-C-D。大家可以理解,如果来的是一个想启动activity B的intent,那么由于B不在栈顶,B的一个新实例就会被创建,即使它的运行模式是singleTop。

Note: When a new instance of an activity is created, the user can press the BACK key to return to the previous activity. But when an existing instance of an activity handles a new intent, the user cannot press the BACK key to return to the state of the activity before the new intent arrived in onNewIntent().

注意:当一个activity的新实例被创建时,用户可以按BACK键回到之前的activity。但是如果是这个activity的已经存在的实例处理的这个intent,用户不能使用BACK键导航回intent到达之前的状态。

"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.
系统创建一个新的任务,而且将activity作为新任务的根activity。但是,如果在之前的任务里,此activity的一个实例已经存在,系统则会将intent通过onNewIntent()方法发送给这个已经存在的实例。而不是创建一个新实例。一次只能有activity的一个实例存在。

Note: Although the activity starts in a new task, the BACK key still returns the user to the previous activity.

注意:尽管activity启动了一个新的任务,使用Back键,仍然会回到先前的那个activity。

"singleInstance".
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.
与”singleTask“基本相同,除了,在保存这个activity实例的任务里,系统不会运行任何其他的activity。此activtiy是它的任务里的唯一一个activity,由此activity启动的任何activity,都将在一个新的任务里启动。

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.

举个别的例子,Android浏览器应用声明了,浏览网页的activity应该总是在它自己的任务里打开——通过在<actiivty>元素里指定singleTask运行模式。这意味着:如果你的应用产生一个打开Android浏览器的intent,那么Android浏览器的activity就不会和你的应用放在同一个任务里。相反,浏览器会启动一个新任务,若浏览器已经有了一个运行在后台的任务,这个任务就会到前台来运行。

Regardless of whether an activity starts in a new task or in the same task as the activity that started it, the BACK key always takes the user to the previous activity. However, if you start an activity from your task (Task A) that specifies the singleTask launch mode, then that activity might have an instance in the background that belongs to a task with its own back stack (Task B). In this case, when Task B is brought forward to handle a new intent, the BACK key first navigates backward through the activities in Task B before returning to the top-most activity in Task A. Figure 4 visualizes this type of scenario.

不管是activity开启一个新任务还是它和开启的activity在同一个任务里,Back键都可以导航回之前的activity。但是,如果你从一个指定了singleTask的任务(任务A)里启动了一个activity,而且此activity已经有一个实例,在后台运行的任务(任务B)里,这种情况下,当任务B被带到前台来运行时,Back键会先导航到任务B的活动栈的下一个activity,然后回到任务A里的栈顶activity。图4描述了这个场景。

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 (Task B), then the entire back stack also comes forward, on top of the current task (Task A).

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 overriden by flags included with the intent that start your activity, as discussed in the next section.

注意:使用lauchMode属性来约束activity的这种行为可以被重写,通过intent的标志位,如下面部分讨论。

Using Intent flags

使用intent标志

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:

当开始一个activity,你可以修改默认的此activity关联到它的任务的方式,通过修改传递到startActivity()方法的intent的标志位。可用于修改默认行为的标志位是:

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 in onNewIntent().
在一个新的任务里开始activity。如果存在一个任务,包含你想启动的那个activity,那么这个任务就会来到前台运行,以它最后运行时的状态。而这个activity也会在onNewIntent()方法里收到一个新的intent。

This produces the same behavior as the "singleTask" launchMode value, discussed in the previous section.

这和前一部分讨论的”singleTask“运行模式是一样的。

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.

如果要启动的activity就是当前的actiivty(在栈顶的那个),那么已经存在的实例收到一个信息,去调用onNewIntent()方法,而不是创建一个新的实例

这和前一部分讨论的”singleTop“运行模式是一样的。

FLAG_ACTIVITY_CLEAR_TOP
If the activity being started 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 are destroyed and this intent is delivered to the resumed instance of the activity (now on top), through onNewIntent()).
如果要启动的activity在当前任务里已经运行了,那么在任务的活动栈里,所有处于它上面的activity全部被销毁,此activity就处于栈顶了,让它恢复运行的intent会发送到它的onNewIntent()方法里。

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.

FLAG_ACTIVITY_CLEAR_TOP 最常与FLAG_ACTIVITY_NEW_TASK联合在一起使用。联合使用时,这些标志可以定位在别的任务里的已经存在的activity,而且将它放到栈顶,以对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".

注意:如果指定activity的运行模式是”standard",它同样会从栈里删除,然后在它的位置运行一个新的实例。那是因为当运行模式是“standard”时,对一个新的intent,总会创建一个新的activity的实例。

Handling affinities

处理偏好

The affinity indicates which task an activity prefers to belong to. By default, all the activities from the same application have an affinity for each other. So, by default, all activities in the same application prefer to be in the same task. However, you can modify the default affinity for an activity. Activities defined in different applications can share an affinity, or activities defined in the same application can be assigned different task affinities.

affinity描述了一个activity更倾向于属于哪个任务。默认情况下,同一个应用里的所有activity,大家一起共享一个affinity。所以,在同一个应用里的所有activity就更倾向于在一个任务里了。但是,每个activity的affinity都可以修改。在不同的应用里的affinity可以共享一个affinity,同一个应用里的不同activity也可以指定不同的任务affinity。

You can modify the affinity for any given activity with the taskAffinity attribute of the <activity> element.

你可以通过<activity>元素的taskAffinity属性,来修改任何一个activity的affinity。

The taskAffinity attribute takes a string value, which must be unique from the default package name declared in the <manifest> element, because the system uses that name to identify the default task affinity for the application.

taskAffinity必须被赋于一个string值,而且不能与<manifest>元素里声明的默认包名相同。因为系统要使用包名来确定应用的默认task affinity。

The affinity comes into play in two circumstances:

下面两种情况会使用到affinity:

  • When the intent that launches an activity contains the FLAG_ACTIVITY_NEW_TASK flag.
  • 当启动一个activity的intent包含FLAG_ACTIVITY_NEW_TASK标志。

    A new activity is, by default, launched into the task of the activity that called startActivity(). It's pushed onto the same back stack as the caller. However, if the intent passed tostartActivity() contains the FLAG_ACTIVITY_NEW_TASK flag, the system looks for a different task to house the new activity. Often, it's a new task. However, it doesn't have to be. If there's already an existing task with the same affinity as the new activity, the activity is launched into that task. If not, it begins a new task.

    默认地,一个新activity通过调用startActivity()启动,它然后被压入与调用者相同的栈里。但是如果调用它的intent,包含了FLAG_ACTIVITY_NEW_TASK标志位,系统就会为这个新activity找个别的任务。通常,它是一个新任务。但也不一定,如果已经存在一个任务,与这个activity有相同的affinity,activity就会在它里面运行。否则,开始一个新任务。

    If this flag causes an activity to begin a new task and the user presses the HOME key to leave it, there must be some way for the user to navigate back to the task. Some entities (such as the notification manager) always start activities in an external task, never as part of their own, so they always put FLAG_ACTIVITY_NEW_TASK in the intents they pass to startActivity(). If you have an activity that can be invoked by an external entity that might use this flag, take care that the user has a independent way to get back to the task that's started, such as with a launcher icon (the root activity of the task has a CATEGORY_LAUNCHER intent filter; see the Starting a task section below).

    如果标志位导致activity开始了一个新的任务,那用户按Home键离开它时,必然存在某种方法,让用户导航回这个任务。有些entity(比如notification管理器),总是在外部的任务里开始activity,从不作为它们自己的一部分,所以,他们在向startActivity()传递intent时,总是带上标志位FLAG_ACTIVITY_NEW_TASK。如果你有一个activity,被外部的entity调用,就可能使用到这个标志位。要注意用户有一个独立的方法来回到这个新启动的任务,比如通过程序图标(此任务的根activity有一个 CATEGORY_LAUNCHER intent filter,看下面的Starting a task部分)。

  • When an activity has its allowTaskReparenting attribute set to "true".
  • 当一个activity有它自己的allowTaskReparenting 属性,并被设置为"true"

    In this case, the activity can move from the task it starts to the task it has an affinity for, when that task comes to the foreground.

    这种情况下,activity可以从启动它的任务,跳到与它有相同的affinity的任务,当那个任务来到前台运行时。

    For example, suppose that an activity that reports weather conditions in selected cities is defined as part of a travel application. It has the same affinity as other activities in the same application (the default application affinity) and it allows re-parenting with this attribute. When one of your activities starts the weather reporter activity, it initially belongs to the same task as your activity. However, when the travel application's task comes to the foreground, the weather reporter activity is reassigned to that task and displayed within it.

    比如,假设有一个报告天气情况的activity,它被作为一个旅行应用的一部分。它与同一个应用里的其他activity有相同的affinity,但是它通过这个属性允许re-parenting。当你的某个activity开始了这个天气汇报activity,它开始的时候与你的activity在同一个任务里。但是,当旅行应用来到前台运行时,天气汇报activity就重属于那个任务去了,而且在那个任务里显示。

Tip: If an .apk file contains more than one "application" from the user's point of view, you probably want to use the taskAffinity attribute to assign different affinities to the activities associated with each "application".

提示:如果一个.apk文件包含不只一个“应用”(从用户角度来说的“应用”),你可能会想使用taskAffinitiy属性来给这些关联到自己的“应用”的activity指定不同的affinity。

Clearing the back stack

清除活动栈

If the user leaves a task for a long time, the system clears the task of all activities except the root activity. When the user returns to the task again, only the root activity is restored. The system behaves this way, because, after an extended amount of time, users likely have abandoned what they were doing before and are returning to the task to begin something new.

如果用户离开一个任务太久, 系统会清空除了根activity以外的所有activity。当用户返回到这个任务时,只有根activity保存下来。系统这样做是因为,过了足够长的一段时间以后,用户基本上已经忘了他们之前做了什么了,他们回来是想做一些新的事情。

There are some activity attributes that you can use to modify this behavior:

下面有一些activity属性用于修改这种行为:

alwaysRetainTaskState
If this attribute is set to "true" in the root activity of a task, the default behavior just described does not happen. The task retains all activities in its stack even after a long period.
如果这个属性在一个任务的根activity里被设为“true”,上面描述的默认行为就不会在发生了。即使过了很长一段时间,任务仍然会保留着所有的activity。
clearTaskOnLaunch
If this attribute is set to "true" in the root activity of a task, the stack is cleared down to the root activity whenever the user leaves the task and returns to it. In other words, it's the opposite ofalwaysRetainTaskState. The user always returns to the task in its initial state, even after a leaving the task for only a moment。
如果这个属性在一个任务的根activity里被设为“true”,一旦用户离开这个任务,再回来时,活动栈就已经被清空到只剩下根activity了。换句话说,它是alwaysRetainTaskState的反面。即使只离开这个任务一秒钟,再回到它时,它已经是初始状态了。
finishOnTaskLaunch
This attribute is like clearTaskOnLaunch, but it operates on a single activity, not an entire task. It can also cause any activity to go away, including the root activity. When it's set to "true", the activity remains part of the task only for the current session. If the user leaves and then returns to the task, it is no longer present.
这个属性类似clearTaskOnLauch。但是它只操作一个单独的activity,而不是整个任务。它可以让任何一个activity消失,甚至包括根activity。如果它被设为“true”,activity只在当前会话中属于这个任务的一部分。用户离开再回到这个任务,它已经再也不存在了。

Starting a task

开始一个任务

You can set up an activity as the entry point for a task by giving it an intent filter with "android.intent.action.MAIN" as the specified action and"android.intent.category.LAUNCHER" as the specified category. For example:

你可以设置一个activity作为一个任务的入口点,通过给它一个intent filter,action属性为“android.intent.action.MAIN",category属性为"android.intent.catagory.LAUNCHER"。例如:

<activity ... >    <intent-filter ... >        <action android:name="android.intent.action.MAIN" />        <category android:name="android.intent.category.LAUNCHER" />    </intent-filter>    ...</activity>

An intent filter of this kind causes an icon and label for the activity to be displayed in the application launcher, giving users a way to launch the activity and to return to the task that it creates any time after it has been launched.

这种类型的intent filter为这个activity生成一个图标和标签,显示在应用启动器里。用户可以通过图标和标签来运行这个activity,在它运行之后的任意时间,使用图标和标签回到这个任务。

This second ability is important: Users must be able to leave a task and then come back to it later using this activity launcher. For this reason, the two launch modes that mark activities as always initiating a task, "singleTask" and ""singleInstance", should be used only when the activity has an ACTION_MAIN and a CATEGORY_LAUNCHER filter. Imagine, for example, what could happen if the filter is missing: An intent launches a "singleTask" activity, initiating a new task, and the user spends some time working in that task. The user then presses the HOME key. The task is now sent to the background and not visible. Because it is not represented in the application launcher, the user has no way to return to the task.

第二个能力很重要。用户必须能离开一个任务,然后还可以使用activity运行器回到这个任务。为此,初始化一个任务时,总会使用两个特殊的运行模式,”singleTask“和”singleInstance“,它们应该只在activity拥有一个ACTION_MAIN 和一个CATEGORY_LAUNCHER filter时使用。想象一下,如果没有这个filter,将会发生什么:一个intent运行一个”singleTask“activity,初始化一个任务,然后用户花费一些时间在那个任务上。当用户按Home键以后,这个任务就进入后台运行,不可见了。由于它在应用启动器里没有对应的图标什么的,用户再没有办法回到这个任务了。

For those cases where you don't want the user to be able to return to an activity, set the <activity> element's finishOnTaskLaunch to "true" (see Clearing the stack).

原创粉丝点击