summaryrefslogtreecommitdiff
path: root/docs/html-intl/intl/zh-cn/guide/components/tasks-and-back-stack.jd
blob: 07fdf6e80a027c98705f0060ad4a519fabc168ce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
page.title=任务和返回栈
parent.title=Activity
parent.link=activities.html
@jd:body

<div id="qv-wrapper">
<div id="qv">

<h2>本文内容</h2>
<ol>
<li><a href="#ActivityState">保存 Activity 状态</a></li></li>
<li><a href="#ManagingTasks">管理任务</a>
  <ol>
    <li><a href="#TaskLaunchModes">定义启动模式</a></li>
    <li><a href="#Affinities">处理关联</a></li>
    <li><a href="#Clearing">清理返回栈</a></li>
    <li><a href="#Starting">启动任务</a></li>
  </ol>
</li>
</ol>

<h2>文章</h2>
<ol>
  <li><a href="http://android-developers.blogspot.com/2010/04/multitasking-android-way.html">
Android 多任务运行机制</a></li>
</ol>

<h2>另请参阅</h2>
<ol>
  <li><a href="{@docRoot}design/patterns/navigation.html">Android
设计:导航</a></li>
  <li><a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}
清单文件元素</a></li>
  <li><a href="{@docRoot}guide/components/recents.html">概览屏幕</a></li>
</ol>
</div>
</div>


<p>应用通常包含多个<a href="{@docRoot}guide/components/activities.html">Activity</a>。每个 Activity 均应围绕用户可以执行的特定操作设计,并且能够启动其他 Activity。

例如,电子邮件应用可能有一个 Activity 显示新邮件的列表。用户选择某邮件时,会打开一个新 Activity 以查看该邮件。
</p>

<p>一个 Activity 甚至可以启动设备上其他应用中存在的 Activity。例如,如果应用想要发送电子邮件,则可将 Intent 定义为执行“发送”操作并加入一些数据,如电子邮件地址和电子邮件。

然后,系统将打开其他应用中声明自己处理此类
 Intent 的 Activity。在这种情况下, Intent 
是要发送电子邮件,因此将启动电子邮件应用的“撰写”Activity(如果多个 Activity 支持相同
 Intent,则系统会让用户选择要使用的 Activity)。发送电子邮件时,Activity 将恢复,看起来好像电子邮件 Activity 是您的应用的一部分。
即使这两个 Activity 可能来自不同的应用,但是
Android 仍会将 Activity 保留在相同的任务中,以维护这种无缝的用户体验。<em></em>
</p>

<p>任务是指在执行特定作业时与用户交互的一系列 Activity。
这些 Activity 按照各自的打开顺序排列在堆栈(即“返回栈”)中。<em></em>
</p>

<!-- SAVE FOR WHEN THE FRAGMENT DOC IS ADDED
<div class="sidebox-wrapper">
<div class="sidebox">
<h3>Adding fragments to a task's back stack</h3>

<p>Your activity can also include {@link android.app.Fragment}s to the back stack. For example,
suppose you have a two-pane layout using fragments, one of which is a list view (fragment A) and the
other being a layout to display an item from the list (fragment B). When the user selects an item
from the list, fragment B is replaced by a new fragment (fragment C). In this case, it might be
desireable for the user to navigate back to reveal fragment B, using the <em>Back</em> button.</p>
<p>In order to add fragment B to the back stack so that this is possible, you must call {@link
android.app.FragmentTransaction#addToBackStack addToBackStack()} before you {@link
android.app.FragmentTransaction#commit()} the transaction that replaces fragment B with fragment
C.</p>
<p>For more information about using fragments and adding them to the back stack, see the {@link
android.app.Fragment} class documentation.</p>

</div>
</div>
-->

<p>设备主屏幕是大多数任务的起点。当用户触摸应用启动器中的图标(或主屏幕上的快捷键)时,该应用的任务将出现在前台。

如果应用不存在任务(应用最近未曾使用),则会创建一个新任务,并且该应用的“主”Activity 将作为堆栈中的根 Activity 打开。

 </p>

<p>当前 Activity 启动另一个 Activity 时,该新 Activity 会被推送到堆栈顶部,成为焦点所在。
前一个 Activity 仍保留在堆栈中,但是处于停止状态。Activity 停止时,系统会保持其用户界面的当前状态。
用户按“返回”按钮时,当前 Activity 会从堆栈顶部弹出(Activity 被销毁),而前一个 Activity 恢复执行(恢复其 UI 的前一状态)。<em></em>


堆栈中的 Activity 永远不会重新排列,仅推入和弹出堆栈:由当前 Activity 启动时推入堆栈;用户使用“返回”按钮退出时弹出堆栈。<em></em>

因此,返回栈以“后进先出”对象结构运行。

图 1 通过时间线显示 Activity 之间的进度以及每个时间点的当前返回栈,直观呈现了这种行为。

</p>

<img src="{@docRoot}images/fundamentals/diagram_backstack.png" alt="" />
<p class="img-caption"><strong>图 1. </strong>显示任务中的每个新 Activity 如何向返回栈添加项目。
用户按“返回”按钮时,当前 Activity 随即被销毁,而前一个 Activity 恢复执行。<em></em>

</p>


<p>如果用户继续按“返回”,堆栈中的相应 Activity 就会弹出,以显示前一个 Activity,直到用户返回主屏幕为止(或者,返回任务开始时正在运行的任意 Activity)。<em></em>


当所有 Activity 均从堆栈中删除后,任务即不复存在。</p>

<div class="figure" style="width:287px">
<img src="{@docRoot}images/fundamentals/diagram_multitasking.png" alt="" /> <p
class="img-caption"><strong>图 2. </strong>两个任务:任务 B
在前台接收用户交互,而任务 A 则在后台等待恢复。</p>
</div>
<div class="figure" style="width:215px">
  <img src="{@docRoot}images/fundamentals/diagram_multiple_instances.png" alt="" /> <p
class="img-caption"><strong>图 3. </strong>一个 Activity 将多次实例化。</p>
</div>

<p>任务是一个有机整体,当用户开始新任务或通过“主页”按钮转到主屏幕时,可以移动到“后台”。<em></em>
尽管在后台时,该任务中的所有 Activity 全部停止,但是任务的返回栈仍旧不变,也就是说,当另一个任务发生时,该任务仅仅失去焦点而已,如图 2 中所示。


然后,任务可以返回到“前台”,用户就能够回到离开时的状态。
例如,假设当前任务(任务 A)的堆栈中有三个 Activity,即当前 Activity 下方还有两个 Activity。
用户先按“主页”按钮,然后从应用启动器启动新应用。<em></em>

显示主屏幕时,任务 A
进入后台。新应用启动时,系统会使用自己的 Activity 堆栈为该应用启动一个任务(任务
B)。与该应用交互之后,用户再次返回主屏幕并选择最初启动任务 A 的应用。现在,任务 A 出现在前台,其堆栈中的所有三个 Activity 保持不变,而位于堆栈顶部的 Activity 则会恢复执行。



此时,用户还可以通过转到主屏幕并选择启动该任务的应用(或者,通过从<a href="{@docRoot}guide/components/recents.html">概览屏幕</a>选择该应用的任务)切换回任务 B。这是 Android 系统中的一个多任务示例。



</p>

<p class="note"><strong>注:</strong>后台可以同时运行多个任务。但是,如果用户同时运行多个后台任务,则系统可能会开始销毁后台 Activity,以回收内存资源,从而导致 Activity 状态丢失。请参阅下面有关<a href="#ActivityState"> Activity 状态</a>的部分。


</p>

<p>由于返回栈中的 Activity 永远不会重新排列,因此如果应用允许用户从多个 Activity 中启动特定 Activity,则会创建该 Activity 的新实例并推入堆栈中(而不是将 Activity 的任一先前实例置于顶部)。


因此,应用中的一个 Activity 可能会多次实例化(即使 Activity 来自不同的任务),如图 3 所示。
因此,如果用户使用“返回”按钮向后导航,则会按 Activity 每个实例的打开顺序显示这些实例(每个实例的 UI 状态各不相同)。<em></em>


但是,如果您不希望 Activity 多次实例化,则可修改此行为。
具体操作方法将在后面的<a href="#ManagingTasks">管理任务</a>部分中讨论。</p>


<p>Activity 和任务的默认行为总结如下:</p>

<ul>
  <li>当 Activity A 启动 Activity B 时,Activity A 将会停止,但系统会保留其状态(例如,滚动位置和已输入表单中的文本)。如果用户在处于 Activity B 时按“返回”按钮,则 Activity A 将恢复其状态,继续执行。<em></em>


</li>
  <li>用户通过按“主页”按钮离开任务时,当前 Activity 将停止且其任务会进入后台。<em></em>

系统将保留任务中每个 Activity 的状态。如果用户稍后通过选择开始任务的启动器图标来恢复任务,则任务将出现在前台并恢复执行堆栈顶部的 Activity。

</li>
  <li>如果用户按“返回”按钮,则当前 Activity 会从堆栈弹出并被销毁。<em></em>

堆栈中的前一个 Activity 恢复执行。销毁 Activity 时,系统绝对不会保留该 Activity 的状态。<em></em>
</li>
  <li>即使来自其他任务,Activity 也可以多次实例化。</li>
</ul>


<div class="note design">
<p><strong>导航设计</strong></p>
  <p>如需了解有关 Android 应用导航工作方式的详细信息,请阅读 Android 设计的<a href="{@docRoot}design/patterns/navigation.html">导航</a>指南。</p>
</div>


<h2 id="ActivityState">保存 Activity 状态</h2>

<p>正如上文所述,当 Activity 停止时,系统的默认行为会保留其状态。
这样一来,当用户导航回到上一个 Activity 时,其用户界面与用户离开时一样。
但是,在 Activity 被销毁且必须重建时,您可以而且<strong>应当</strong>主动使用回调方法保留 Activity 的状态。

</p>

<p>系统停止您的一个 Activity 时(例如,新 Activity 启动或任务转到前台),如果系统需要回收系统内存资源,则可能会完全销毁该 Activity。

发生这种情况时,有关该 Activity 状态的信息将会丢失。如果发生这种情况,系统仍会知道该 Activity 存在于返回栈中,但是当该 Activity 被置于堆栈顶部时,系统一定会重建 Activity(而不是恢复 Activity)。


为了避免用户的工作丢失,您应主动通过在 Activity 中实现
{@link android.app.Activity#onSaveInstanceState onSaveInstanceState()}
回调方法来保留工作。
</p>

<p>如需了解有关如何保存 Activity 状态的详细信息,请参阅<a href="{@docRoot}guide/components/activities.html#SavingActivityState">Activity</a>文档。
</p>



<h2 id="ManagingTasks">管理任务</h2>

<p>Android 管理任务和返回栈的方式(如上所述,即:将所有连续启动的 Activity 放入同一任务和“后进先出”堆栈中)非常适用于大多数应用,而您不必担心 Activity 如何与任务关联或者如何存在于返回栈中。


但是,您可能会决定要中断正常行为。
也许您希望应用中的 Activity 在启动时开始新任务(而不是放置在当前任务中);或者,当启动 Activity 时,您希望将其现有实例上移一层(而不是在返回栈的顶部创建新实例);或者,您希望在用户离开任务时,清除返回栈中除根 Activity 以外的所有其他 Activity。



</p>

<p>通过使用 <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a> 清单文件元素中的属性和传递给 {@link android.app.Activity#startActivity startActivity()}
的 Intent 中的标志,您可以执行所有这些操作以及其他操作。

</p>

<p>在这一方面,您可以使用的主要 <a href="{@docRoot}guide/topics/manifest/activity-element.html">
{@code &lt;activity&gt;}</a> 属性包括:</p>

<ul class="nolist">
  <li><a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">
  {@code taskAffinity}</a></li>
  <li><a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">
  {@code launchMode}</a></li>
  <li><a href="{@docRoot}guide/topics/manifest/activity-element.html#reparent">
  {@code allowTaskReparenting}</a></li>
  <li><a href="{@docRoot}guide/topics/manifest/activity-element.html#clear">
  {@code clearTaskOnLaunch}</a></li>
  <li><a href="{@docRoot}guide/topics/manifest/activity-element.html#always">
  {@code alwaysRetainTaskState}</a></li>
  <li><a href="{@docRoot}guide/topics/manifest/activity-element.html#finish">
  {@code finishOnTaskLaunch}</a></li>
</ul>

<p>您可以使用的主要 Intent 标志包括:</p>

<ul class="nolist">
  <li>{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}</li>
  <li>{@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP}</li>
  <li>{@link android.content.Intent#FLAG_ACTIVITY_SINGLE_TOP}</li>
</ul>

<p>在下文中,您将了解如何使用这些清单文件属性和 Intent 
标志定义 Activity 与任务的关联方式,以及 Activity 在返回栈中的行为方式。</p>

<p>此外,我们还单独介绍了有关如何在概览屏幕中显示和管理任务与 Activity 的注意事项。
如需了解详细信息,请参阅<a href="{@docRoot}guide/components/recents.html">概览屏幕</a>。
通常,您应该允许系统定义任务和 Activity 在概览屏幕中的显示方法,并且无需修改此行为。
</p>

<p class="caution"><strong>注意:</strong>大多数应用都不得中断 Activity 和任务的默认行为:
如果确定您的 Activity 必须修改默认行为,当使用“返回”按钮从其他 Activity 和任务导航回到该 Activity 时,请务必要谨慎并确保在启动期间测试该 Activity 的可用性。请确保测试导航行为是否有可能与用户的预期行为冲突。<em></em>


</p>


<h3 id="TaskLaunchModes">定义启动模式</h3>

<p>启动模式允许您定义 Activity 的新实例如何与当前任务关联。
您可以通过两种方法定义不同的启动模式:</p>
<ul class="nolist">
  <li><a href="#ManifestForTasks">使用清单文件</a>
    <p>在清单文件中声明 Activity 时,您可以指定 Activity 在启动时应该如何与任务关联。
</li>
  <li><a href="#IntentFlagsForTasks">使用 Intent 标志</a>
    <p>调用 {@link android.app.Activity#startActivity startActivity()}
时,可以在 {@link android.content.Intent}
中加入一个标志,用于声明新 Activity 如何(或是否)与当前任务关联。</p></li>
</ul>

<p>因此,如果 Activity
A 启动 Activity B,则 Activity B 可以在其清单文件中定义它应该如何与当前任务关联(如果可能),并且 Activity A 还可以请求 Activity B
应该如何与当前任务关联。如果这两个 Activity 均定义 Activity B
应该如何与任务关联,则 Activity A 的请求(如 Intent 中所定义)优先级要高于 Activity
B 的请求(如其清单文件中所定义)。</p>

<p class="note"><strong>注:</strong>某些适用于清单文件的启动
模式不可用作 Intent 标志,同样,某些可用作 Intent 
标志的启动模式无法在清单文件中定义。</p>


<h4 id="ManifestForTasks">使用清单文件</h4>

<p>在清单文件中声明 Activity 时,您可以使用 <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>
元素的 <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code
launchMode}</a>
属性指定 Activity 应该如何与任务关联。</p>

<p><a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code
launchMode}</a>
属性指定有关应如何将 Activity 启动到任务中的指令。您可以分配给
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">launchMode</a></code>
属性的启动模式共有四种:</p>

<dl>
<dt>{@code "standard"}(默认模式)</dt>
  <dd>默认。系统在启动 Activity 的任务中创建 Activity 的新实例并向其传送
 Intent。Activity 可以多次实例化,而每个实例均可属于不同的任务,并且一个任务可以拥有多个实例。
</dd>
<dt>{@code "singleTop"}</dt>
  <dd>如果当前任务的顶部已存在 Activity 的一个实例,则系统会通过调用该实例的
{@link
android.app.Activity#onNewIntent onNewIntent()}
方法向其传送 Intent,而不是创建 Activity 的新实例。Activity 可以多次实例化,而每个实例均可属于不同的任务,并且一个任务可以拥有多个实例(但前提是位于返回栈顶部的 Activity 并不是 Activity 的现有实例)。<em></em>


  <p>例如,假设任务的返回栈包含根 Activity A 以及 Activity B、C
和位于顶部的 D(堆栈是 A-B-C-D;D 位于顶部)。收到针对 D 类 Activity 的 Intent。如果 D
具有默认的 {@code "standard"} 启动模式,则会启动该类的新实例,且堆栈会变成 A-B-C-D-D。但是,如果 D 的启动模式是 {@code "singleTop"},则 D
的现有实例会通过 {@link
android.app.Activity#onNewIntent onNewIntent()} 接收 Intent,因为它位于堆栈的顶部;而堆栈仍为
A-B-C-D。但是,如果收到针对 A 类 Activity 的 Intent,则会向堆栈添加 B 的新实例,即便其启动模式为 {@code "singleTop"} 也是如此。

</p>
  <p class="note"><strong>注:</strong>为某个 Activity 创建新实例时,用户可以按“返回”按钮返回到前一个 Activity。<em></em>
但是,当 Activity 的现有实例处理新
 Intent 时,则在新 Intent 到达
{@link android.app.Activity#onNewIntent
onNewIntent()}
之前,用户无法按“返回”<em></em>按钮返回到 Activity 的状态。
</p>
</dd>

<dt>{@code "singleTask"}</dt>
  <dd>系统创建新任务并实例化位于新任务底部的 Activity。但是,如果该 Activity 的一个实例已存在于一个单独的任务中,则系统会通过调用现有实例的 {@link
android.app.Activity#onNewIntent
onNewIntent()} 方法向其传送
 Intent,而不是创建新实例。一次只能存在 Activity 的一个实例。

  <p class="note"><strong>注:</strong>尽管 Activity 在新任务中启动,但是用户按“返回”<em></em>按钮仍会返回到前一个 Activity。
</p></dd>
<dt>{@code "singleInstance"}。</dt>
  <dd>与
{@code "singleTask"} 相同,只是系统不会将任何其他 Activity 启动到包含实例的任务中。该 Activity 始终是其任务唯一仅有的成员;由此 Activity 启动的任何 Activity 均在单独的任务中打开。
</dd>
</dl>


<p>我们再来看另一示例,Android 浏览器
应用声明 Web 浏览器 Activity 应始终在其自己的任务中打开(通过在 <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a> 元素中指定 {@code singleTask}
启动模式)。这意味着,如果您的应用发出打开
Android 浏览器的
 Intent,则其 Activity 与您的应用位于不同的任务中。<em></em>相反,系统会为浏览器启动新任务,或者如果浏览器
已有任务正在后台运行,则会将该任务上移一层以处理新
 Intent。</p>

<p>无论 Activity 是在新任务中启动,还是在与启动 Activity 相同的任务中启动,用户按“返回”<em></em>按钮始终会转到前一个 Activity。
但是,如果启动指定
{@code singleTask}
启动模式的 Activity,则当某后台任务中存在该 Activity 的实例时,整个任务都会转移到前台。此时,返回栈包括上移到堆栈顶部的任务中的所有 Activity。

图 4 显示了这种情况。</p>

<img src="{@docRoot}images/fundamentals/diagram_backstack_singletask_multiactivity.png" alt="" />
<p class="img-caption"><strong>图 4. </strong>显示如何将启动模式为“singleTask”的 Activity 添加到返回栈。
如果 Activity 已经是某个拥有自己的返回栈的后台任务的一部分,则整个返回栈也会上移到当前任务的顶部。

</p>

<p>如需了解有关在清单文件中使用启动模式的详细信息,请参阅
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
元素文档,其中更详细地讨论了 {@code launchMode}
属性和可接受的值。</p>

<p class="note"><strong>注:</strong>使用 <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a>
属性为 Activity 指定的行为可由 Intent 
附带的 Activity 启动标志替代,下文将对此进行讨论。</p>



<h4 id="#IntentFlagsForTasks">使用 Intent 标志</h4>

<p>启动 Activity 时,您可以通过在传递给 {@link
android.app.Activity#startActivity startActivity()} 的 Intent 
中加入相应的标志,修改 Activity 与其任务的默认关联方式。可用于修改默认行为的标志包括:
</p>

<p>
  <dt>{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}</dt>
    <dd>在新任务中启动 Activity。如果已为正在启动的 Activity 运行任务,则该任务会转到前台并恢复其最后状态,同时 Activity 会在
{@link android.app.Activity#onNewIntent onNewIntent()} 中收到新
 Intent。
    <p>正如前文所述,这会产生与 {@code "singleTask"} <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a>
值相同的行为。</p></dd>
  <dt>{@link android.content.Intent#FLAG_ACTIVITY_SINGLE_TOP}</dt>
    <dd>如果正在启动的 Activity 是当前 Activity(位于返回栈的顶部),则
现有实例会接收对 {@link android.app.Activity#onNewIntent onNewIntent()}
的调用,而不是创建 Activity 的新实例。
    <p>正如前文所述,这会产生与 {@code "singleTop"} <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a>
值相同的行为。</p></dd>
  <dt>{@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP}</dt>
    <dd>如果正在启动的 Activity 已在当前任务中运行,则会销毁当前任务顶部的所有 Activity,并通过 {@link android.app.Activity#onNewIntent onNewIntent()}
将此 Intent 传递给 Activity 已恢复的实例(现在位于顶部),而不是启动该 Activity 的新实例。


    <p>产生这种行为的 <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">{@code launchMode}</a>
属性没有值。</p>
    <p>{@code FLAG_ACTIVITY_CLEAR_TOP} 通常与
{@code FLAG_ACTIVITY_NEW_TASK}
结合使用。一起使用时,通过这些标志,可以找到其他任务中的现有 Activity,并将其放入可从中响应 Intent 
的位置。 </p>
    <p class="note"><strong>注:</strong>如果指定 Activity 的启动模式为
{@code "standard"},则该 Activity 也会从堆栈中删除,并在其位置启动一个新实例,以便处理传入的 Intent。

这是因为当启动模式为 {@code "standard"}
时,将始终为新 Intent 创建新实例。 </p>
</dd>
</dl>





<h3 id="Affinities">处理关联</h3>

<p>“关联”指示 Activity 优先属于哪个任务。<em></em>默认情况下,同一应用中的所有 Activity 彼此关联。
因此,默认情况下,同一应用中的所有 Activity 优先位于相同任务中。
不过,您可以修改 Activity 的默认关联。
在不同应用中定义的 Activity 可以共享关联,或者可为在同一应用中定义的 Activity 分配不同的任务关联。

</p>

<p>可以使用 <a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity&gt;}</a>
元素的
<a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">{@code taskAffinity}</a> 属性修改任何给定 Activity 的关联。</p>

<p><a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">{@code taskAffinity}</a>
属性取字符串值,该值必须不同于
在<a href="{@docRoot}guide/topics/manifest/manifest-element.html">
{@code &lt;manifest&gt;}
</a>元素中声明的默认软件包名称,因为系统使用该名称标识应用的默认任务关联。
</p>

<p>在两种情况下,关联会起作用:</p>
<ul>
  <li>启动 Activity 的 Intent 包含
{@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}
标志。

<p>默认情况下,新 Activity 会启动到调用
{@link android.app.Activity#startActivity startActivity()} 的 Activity 任务中。它将推入与调用方相同的返回栈。
但是,如果传递给
{@link android.app.Activity#startActivity startActivity()}
的 Intent 包含 {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK}
标志,则系统会寻找其他任务来储存新 Activity。这通常是新任务,但未做强制要求。
如果现有任务与新 Activity 具有相同关联,则会将 Activity 启动到该任务中。
否则,将开始新任务。</p>

<p>如果此标志导致 Activity 开始新任务,且用户按“主页”按钮离开,则必须为用户提供导航回任务的方式。<em></em>

有些实体(如通知管理器)始终在外部任务中启动 Activity,而从不作为其自身的一部分启动 Activity,因此它们始终将
{@code FLAG_ACTIVITY_NEW_TASK} 放入传递给
{@link android.app.Activity#startActivity startActivity()}
的 Intent 中。请注意,如果 Activity 能够由可以使用此标志的外部实体调用,则用户可以通过独立方式返回到启动的任务,例如,使用启动器图标(任务的根 Activity 具有
{@link android.content.Intent#CATEGORY_LAUNCHER}
 Intent 过滤器;请参阅下面的<a href="#Starting">启动任务</a>部分)。

</p>
</li>

  <li>Activity 将其<a href="{@docRoot}guide/topics/manifest/activity-element.html#reparent">
{@code allowTaskReparenting}</a> 属性设置为 {@code "true"}。
  <p>在这种情况下,Activity 可以从其启动的任务移动到与其具有关联的任务(如果该任务出现在前台)。
</p>
  <p>例如,假设将报告所选城市天气状况的 Activity 定义为旅行应用的一部分。
它与同一应用中的其他 Activity 具有相同的关联(默认应用关联),并允许利用此属性重定父级。当您的一个 Activity 启动天气预报 Activity 时,它最初所属的任务与您的 Activity 相同。


但是,当旅行应用的任务出现在前台时,系统会将天气预报 Activity 重新分配给该任务并显示在其中。
</p>
</li>
</ul>

<p class="note"><strong>提示</strong>:如果从用户的角度来看,一个 {@code .apk}
文件包含多个“应用”,则您可能需要使用 <a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">{@code taskAffinity}</a>
属性将不同关联分配给与每个“应用”相关的 Activity。</p>



<h3 id="Clearing">清理返回栈</h3>

<p>如果用户长时间离开任务,则系统会清除所有 Activity 的任务,根任务除外。
当用户再次返回到任务时,仅恢复根 Activity。系统这样做的原因是,经过很长一段时间后,用户可能已经放弃之前执行的操作,返回到任务是要开始执行新的操作。

 </p>

<p>您可以使用下列几个 Activity 属性修改此行为: </p>

<dl>
<dt><code><a
href="{@docRoot}guide/topics/manifest/activity-element.html#always">alwaysRetainTaskState</a></code>
</dt>
<dd>如果在任务的根 Activity 中将此属性设置为 {@code "true"},则不会发生刚才所述的默认行为。即使在很长一段时间后,任务仍将所有 Activity 保留在其堆栈中。

</dd>

<dt><code><a
href="{@docRoot}guide/topics/manifest/activity-element.html#clear">clearTaskOnLaunch</a></code></dt>
<dd>如果在任务的根 Activity 中将此属性设置为 {@code "true"},则每当用户离开任务然后返回时,系统都会将堆栈清除到只剩下根 Activity。

换而言之,它与<a href="{@docRoot}guide/topics/manifest/activity-element.html#always">
{@code alwaysRetainTaskState}</a> 正好相反。
即使只离开任务片刻时间,用户也始终会返回到任务的初始状态。
</dd>

<dt><code><a
href="{@docRoot}guide/topics/manifest/activity-element.html#finish">finishOnTaskLaunch</a></code>
</dt>
<dd>此属性类似于
<a href="{@docRoot}guide/topics/manifest/activity-element.html#clear">{@code clearTaskOnLaunch}</a>,但它对单个 Activity 起作用,而非整个任务。
此外,它还有可能会导致任何 Activity 停止,包括根 Activity。
设置为 {@code "true"}
时,Activity 仍是任务的一部分,但是仅限于当前会话。如果用户离开然后返回任务,则任务将不复存在。
</dd>
</dl>




<h3 id="Starting">启动任务</h3>

<p>通过为 Activity 提供一个以 {@code "android.intent.action.MAIN"}
为指定操作、以{@code "android.intent.category.LAUNCHER"}
为指定类别的 Intent 过滤器,您可以将活动设置为任务的入口点。
例如:</p>

<pre>
&lt;activity ... &gt;
    &lt;intent-filter ... &gt;
        &lt;action android:name="android.intent.action.MAIN" /&gt;
        &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
    &lt;/intent-filter&gt;
    ...
&lt;/activity&gt;
</pre>

<p>此类 Intent 过滤器会使 Activity 的图标和标签显示在应用启动器中,让用户能够启动 Activity 并在启动之后随时返回到创建的任务中。


</p>

<p>第二个功能非常重要:用户必须能够在离开任务后,再使用此 Activity 启动器返回该任务。
因此,只有在 Activity 具有
{@link android.content.Intent#ACTION_MAIN}
和 {@link android.content.Intent#CATEGORY_LAUNCHER}
过滤器时,才应该使用将 Activity 标记为“始终启动任务”的两种<a href="#LaunchModes">启动模式</a>,即 {@code "singleTask"} 和
{@code "singleInstance"}。例如,我们可以想像一下如果缺少过滤器会发生什么情况:
 Intent 启动一个 {@code "singleTask"}
Activity,从而启动一个新任务,并且用户花了些时间处理该任务。然后,用户按<em>主页</em>按钮。
任务现已发送到后台,而且不可见。现在,用户无法返回到任务,因为该任务未显示在应用启动器中。
</p>

<p>如果您并不想用户能够返回到 Activity,对于这些情况,请将
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
元素的
<a href="{@docRoot}guide/topics/manifest/activity-element.html#finish">{@code finishOnTaskLaunch}</a>
设置为 {@code "true"}(请参阅<a href="#Clearing">清理堆栈</a>)。</p>

<p>有关如何在概览屏幕中显示和管理任务与 Activity 的更多信息,请参阅<a href="{@docRoot}guide/components/recents.html">概览屏幕</a>。

</p>

<!--
<h2>Beginner's Path</h2>

<p>For more information about how to use intents to
activate other application components and publish the intents to which your components
respond, continue with the <b><a
href="{@docRoot}guide/components/intents-filters.html">Intents and Intent
Filters</a></b> document.</p>
-->