导航

Tasks and Back Stack

Posted on 2017-06-16 00:34  Young哥哥  阅读(213)  评论(0)    收藏  举报

Tasks and Back Stack

任务和返回栈 

应用程序通常包含多个活动。每个活动的设计应以一种特定的行动用户可以执行和其他可以开始活动。例如,一个电子邮件应用程序可能有一个活动来展示一个新的电子邮件列表。当用户选择一个电子邮件,一个新的活动打开查看电子邮件。


一个活动甚至可以开始活动,存在于其他应用程序在设备上。例如,如果您的应用程序想要发送一封电子邮件,您可以定义一个意图执行发送行动,包括一些数据,如电子邮件地址和消息。从另一个应用程序,一个活动声明本身来处理这种意图然后打开。在这种情况下,目的是发送一封电子邮件,电子邮件应用程序的活动开始(如果多个活动支持相同的意图,那么系统允许用户选择使用哪一个)。发送电子邮件时,您的活动简历和好像电子邮件活动是应用程序的一部分。即使活动可能会从不同的应用程序,Android保持这种无缝的用户体验通过保持两个活动相同的任务。

 

一个任务是一个与用户交互的活动集合在执行特定的工作。活动安排在一个堆栈(堆栈),在每个活动的顺序打开。


设备主屏幕是大多数任务的起点。当用户触摸应用程序启动器的图标(或主屏幕上的快捷方式),该应用程序的任务涉及到前台。如果任务不存在为应用程序(应用程序最近没有使用),然后创建一个新的任务,该应用程序打开的主要活动作为根活动堆栈。


当当前活动开始另一个新的活动是推动堆栈的顶部和焦点。之前的活动仍在堆栈,但是停止了。当一个活动停止,系统保留其用户界面的当前状态。当用户按下后退按钮时,当前活动突然从堆栈的顶部(活动被摧毁)和前一个活动恢复(恢复以前状态的UI)。活动在堆栈中从未被重新安排,只有推和破灭stack-pushed压入堆栈由当前活动开始,破灭时使用后退按钮当用户离开它。因此,回栈是一个后进先出对象结构。图1可视化这一行为一个时间表显示活动之间的进展以及当前堆栈在每个时间点。

 

 

 

1所示。表示每一个新的活动任务如何将一个条目添加到堆栈。当用户按下后面披肩按钮时,当前活动被摧毁和前面的活动简历。


如果用户继续推回去,然后每个活动堆栈弹出显示前一个,直到用户返回到主屏幕(或任何活动运行任务开始的时候)。所有活动从堆栈中删除时,该任务已不复存在。

 

 

一个任务是一个有凝聚力的集体,可以移动到背景,当用户开始新的任务或主屏幕,通过theHome按钮。在后台,所有任务的活动都停止了,但是回堆栈任务仍力求从只是失去了焦点而另一个任务,如图2所示。任务可以回到前景,用户可以接他们离开的地方。假设,例如,当前的任务(任务)有三个活动在其stack-two在当前活动。用户按下Homebutton,然后开始一个新的应用程序从应用程序启动器。当主屏幕出现时,任务进入背景。新应用程序启动时,系统开始为该应用程序任务(任务B)有自己的堆栈的活动。与应用程序交互后,用户再次回家,选择最初的应用程序启动任务A .现在,任务涉及到foreground-all三个活动在其堆栈完好无损和活动堆栈的顶部简历。在这一点上,用户还可以切换回任务B通过回家并选择应用程序图标,开始任务(或通过选择最近appsscreen)的应用程序的任务。这是一个多任务在Android上的例子。

:多个任务可以在后台。然而,如果用户正在运行许多后台任务同时,系统可能会开始破坏背景活动为了恢复内存,导致活动状态。看到下面一节关于活动的状态。

 

 

因为活动在堆栈是从来没有重新安排,如果您的应用程序允许用户启动一个特定活动从超过一个活动,一个新实例的创建活动,推动压入堆栈(而不是把以往的实例活动顶部)。因此,一个活动在您的应用程序可能会多次实例化(甚至从不同的任务),如图3所示。因此,如果用户使用后退按钮向后导航,活动的每个实例显示的顺序与它们打开(每个都有自己的UI状态)。但是,您可以修改这个行为,如果你不想让一个活动不止一次被实例化。如何这样做在后面的小节中讨论了关于管理的任务。


总结的默认行为活动和任务:

当活动开始活动,活动停止,但系统保持它的状态(如滚动位置和文本输入形式)。如果用户按下后退按钮在活动,活动的简历状态恢复。


当用户离开任务按按钮,停止当前活动及其任务进入后台。系统保留每个活动的任务的状态。如果用户后来简历任务通过选择发射器的图标,开始任务,任务的前景和简历的活动堆栈的顶部。


如果用户按下后退按钮,当前活动从栈中弹出,摧毁了。之前的活动堆栈恢复。活动被摧毁时,系统不保留活动的状态。


多次活动可以被实例化,甚至从其他任务。

Navigation Design导航设计

 

更多关于Android应用程序导航是如何工作的,Android设计的导航指南。

 

 

Saving Activity State

 

正如上面所讨论的,系统的默认行为保留活动停止时的状态。这样,当用户导航回前一个活动,它的用户界面看起来他们离开的方式。然而,你应该保留你的活动使用回调方法,如果活动是销毁,必须重新创建。


当系统停止你的活动(如当一个新活动开始或任务背景移),系统可能会彻底摧毁这个活动如果需要恢复系统内存。当这一切发生的时候,活动状态信息丢失。如果发生这种情况,系统仍然知道活动在堆栈,但是当活动带到堆栈的顶部系统必须重新创建它(而不是简历)。为了避免失去用户的工作,你应该主动保留通过实现仅有()回调方法在你的活动。


为更多的信息关于如何保存活动状态,看到活动文档。

Managing Tasks

Android的方式管理任务和堆栈,所述上方放置所有活动在相同的任务,开始纷纷后进先出stack-works对于大多数应用程序,你不应该担心你的活动与任务相关联或他们如何存在于栈。然而,你可能会认为你想打断正常的行为。也许你想要一个活动在您的应用程序中开始一个新任务开始时(而不是放置在当前任务);或者,当你开始一个活动,你想提出一个现有的实例(而不是创建一个新的实例上的堆栈);或者,你希望你的背部堆栈的所有活动除了根活动当用户离开任务。


你可以做这些事情,<活动>清单元素的属性和旗帜的意图传递给startActivity()


在这方面,校长您可以使用<活动>属性:

  1. taskAffinity
  2. launchMode
  3. allowTaskReparenting
  4. clearTaskOnLaunch
  5. alwaysRetainTaskState
  6. finishOnTaskLaunch

和校长意图旗帜可以使用:

  1. FLAG_ACTIVITY_NEW_TASK
  2. FLAG_ACTIVITY_CLEAR_TOP
  3. FLAG_ACTIVITY_SINGLE_TOP

在下面几节中,您将看到如何使用这些清单属性和意图旗帜定义活动与任务,以及如何表现在堆栈。


注意:大多数应用程序不应该中断活动和任务的默认行为。如果你确定是必要的活动修改默认的行为,使用谨慎,一定要测试的可用性活动启动,当导航回到它从其他活动和任务后面披肩按钮。一定要测试导航行为,可能与用户的预期行为冲突。

Defining launch modes

启动模式允许您定义一个新实例如何与当前任务相关的活动。您可以定义不同的发射模式在两个方面:

使用清单文件  

 

当你声明一个活动在你的清单文件,您可以指定活动应该如何与任务在启动时。

使用意图的旗帜 

 

当你叫startActivity(),您可以包括一个标志的意图声明如何(或是否)新活动应该与当前任务。

 

这样,如果活动开始活动,活动B可以定义在清单如何与当前任务(如果有的话)和活动也可以请求活动B应该如何与当前的任务。如果两个活动定义如何活动B应该联想到一个任务,然后活动的请求中定义的意图是荣幸在活动B的请求中定义(如清单)

注意:一些发射模式用于manifest文件不可用作为一个意图和旗帜,同样地,一些发射模式可以作为标志的意图不能定义在清单。

Using the manifest file

声明一个活动清单文件时,您可以指定活动应该如何与一个任务使用<活动>元素的launchMode属性。


launchMode属性指定一个教学活动应该如何投入了一个任务。有四个不同的发射模式可以分配到launchMode属性:

"standard" (the default mode)

违约。系统创建一个新实例的活动在任务开始,路线的意图。活动可以多次实例化,每个实例可以属于不同的任务,一个任务可以有多个实例。

"singleTop"

如果活动的一个实例已经存在在当前任务,系统路线意图通过调用其onNewIntent实例()方法,而不是创建一个新的实例的活动。活动可以多次实例化,每个实例可以属于不同的任务,一个任务可以有多个实例(但前提是活动回堆栈的顶部不是现有活动的实例)

 

例如,假设一个任务的堆栈由根活动与活动BCD顶部(顶部堆栈A-B-C-D;D)。活动的目的到达类型D D是否有默认的标准发射模式下,一个类的新实例启动和堆栈A-B-C-D-D。然而,如果D的发射模式是singleTop,D的现有实例接收意图通过onNewIntent(),因为它的堆栈的顶部仍然A-B-C-D。然而,如果一个活动的目的到达B,然后B的一个新实例添加到堆栈,即使发射模式是singleTop

 

 

注意:创建一个新实例的一个活动时,用户可以按后退按钮回到之前的活动。但当现有实例的活动处理新意图,用户不能按后退按钮回到活动在新意图前的状态抵达onNewIntent()

 

singleTask
系统创建一个新的任务和实例化活动的根源的新任务。然而,如果活动的一个实例已经存在在一个单独的任务,系统路线意图通过调用其现有实例onNewIntent()方法,而不是创建一个新的实例。只有一个实例的活动可以同时存在。
注意:尽管活动开始在一个新的任务,仍然后退按钮返回用户以前的活动。

singleInstance
singleTask一样,只是系统不启动任何其他活动任务实例。活动总是单身,只有成员的任务;任何活动开始这一开放在一个单独的任务。

 

另外一个例子,Android浏览器应用程序声明的web浏览器活动应该开放自己的任务指定singleTask <活动>元素的发射模式。这意味着,如果您的应用程序问题的意图打开Android浏览器,其活动并不是放置在与应用程序相同的任务。相反,浏览器或启动一个新任务,如果浏览器已经在后台运行的任务,这个任务是提出处理的新意图。


无论一个活动开始在一个新任务或相同的任务的活动开始,Backbutton总是用户以前的活动。但是,如果你开始一个活动,指定thesingleTask发射模式下,如果一个实例的活动存在于一个后台任务,整个任务转移到前台。在这一点上,现在回堆栈包括所有活动任务提出,在堆栈的顶部。图4展示了这种类型的场景。

 

 

 

4。如何表示一个活动与发射模式singleTask添加到堆栈。如果活动已经后台任务的一部分有自己的堆栈,然后整个堆栈还提出,在当前任务。


关于使用发布模式的更多信息在manifest文件中,请参阅<活动>元素文档,launchMode属性和公认的价值观进行了讨论。


注意:您所指定的行为对你的活动与launchMode属性可以被标记中包含的意图,开始你的活动,作为下一节讨论。

 

Using Intent flags

 

当开始一个活动,您可以修改默认的协会活动,其任务包括旗帜的意图,你提供startActivity()。旗帜可以使用修改默认行为是:


FLAG_ACTIVITY_NEW_TASK
启动活动在一个新的任务。如果一个任务正在运行的活动现在开始,这个任务被带到前台的最后状态恢复和活动收到的新意图inonNewIntent()
这产生了相同的行为singleTasklaunchMode价值,在前一节中讨论。


FLAG_ACTIVITY_SINGLE_TOP
如果活动开始是当前活动(回堆栈的顶部),然后现有实例接收调用onNewIntent(),而不是创建一个新的实例的活动。
这产生了相同的行为singleToplaunchMode价值,在前一节中讨论。


FLAG_ACTIVITY_CLEAR_TOP
如果活动被开始已经运行在当前任务,然后启动一个新实例的活动,而是在其上的所有其他活动被破坏,这活动的意图是交付给恢复实例上(现在),通过onNewIntent())
毫无launchMode属性的值时,产生这种行为。


FLAG_ACTIVITY_CLEAR_TOP常常与FLAG_ACTIVITY_NEW_TASK一起使用。一起使用时,这些标记是一种定位现有的活动在另一个任务并把它在一个位置,它可以响应的目的。


注意:如果指定的发射模式活动是标准,它也是从堆栈中删除,启动一个新实例在其位置来处理传入的意图。这是因为新意图总是创建一个新的实例时,启动模式是标准

 

Handling affinities

亲和力显示哪个任务活动喜欢属于。默认情况下,同一个应用程序的所有活动相互关联。所以,默认情况下,所有活动在同一个应用程序更喜欢相同的任务。但是,您可以修改默认的关联为一个活动。活动定义在不同的应用程序可以共享一个亲和力,或活动定义在相同的应用程序可以分配不同的任务紧密联系。


您可以修改任何活动的亲和力与taskAffinity <活动>元素的属性。


taskAffinity属性将一个字符串值,从默认的包名称必须是惟一的<清单>元素中声明,因为系统使用该名称来识别为应用程序默认任务关联。


亲和力发挥作用的两种情况:

 

当启动一个活动的意图包含FLAG_ACTIVITY_NEW_TASK国旗。
一个新的活动,默认情况下,启动的任务活动,称为startActivity()。它的推到相同的堆栈调用者。然而,如果意图传递给startActivity()包含theFLAG_ACTIVITY_NEW_TASK国旗,系统寻找一个不同的任务房子新活动。通常,这是一个新任务。然而,它没有。如果有已经现有的任务相同的亲和力的新活动,该活动投入了这一任务。如果不是,它开始一个新的任务。
如果这个标志导致一个活动开始一个新的任务,用户按下按钮离开它,必须有某种方式为用户导航回任务。一些实体(如通知经理)总是开始在外部活动任务,从不为自己的一部分,所以他们总是putFLAG_ACTIVITY_NEW_TASK意图传递给startActivity()。如果你有一个活动,可以调用一个外部实体,可能会使用这个标志,照顾,用户有一个独立的方式回到开始的任务,例如一个发射器的图标(根活动任务的aCATEGORY_LAUNCHER意图过滤器,请参阅下面的任务开始部分)

 

当某个活动有其allowTaskReparenting属性设置为true
在这种情况下,活动可以从任务开始了它的亲和力,当涉及到前台这一任务。
例如,假设一个活动,报告天气条件在选定的城市被定义为一个旅行应用程序的一部分。它有相同的亲和力其他活动在同一个应用程序(默认应用程序关联),它允许当这个属性。当你的一个活动开始天气记者活动,它最初属于相同的任务作为你的活动。然而,当旅行应用程序的任务涉及到前台,天气记者活动重新分配任务和显示。

 

提示:如果一个。apk文件包含一个以上的应用程序从用户的角度来看,您可能希望使用taskAffinity属性分配不同的亲和力与每个应用程序相关联的活动。

 

Clearing the back stack

如果用户离开任务很长一段时间,系统清理所有活动的任务除了根活动。当用户再次返回到任务,只有根恢复活动。系统这样的行为,因为,一段时间后,用户可能已经放弃了他们在做什么之前,返回到任务开始新的东西。


有一些活动属性,您可以使用它们来修改这个行为:


alwaysRetainTaskState
如果将该属性设置为true的根活动任务,刚刚描述的默认行为不会发生。保留所有活动的任务堆栈即使在很长一段时间。
clearTaskOnLaunch
如果将该属性设置为true的根活动任务,清除堆栈到根活动当用户离开任务并返回它。换句话说,它的相反的ofalwaysRetainTaskState。用户总是返回到初始状态的任务,即使离开之后的任务只有一个时刻。
finishOnTaskLaunch
这个属性就像clearTaskOnLaunch,但它运行在一个活动,而不是一个完整的任务。它还会引起任何活动消失,包括根活动。当设置为true,该活动是任务的一部分只用于当前会话。如果用户离开,然后返回到任务,它不再是礼物。

 

Starting a task

您可以设置一个活动任务的入口点,给它一个意图过滤器指定“android.intent.action.MAIN”行动和“android.intent.category.LAUNCHER”指定的类别。例如:

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

这种原因的意图过滤器的图标和标签活动显示在应用程序启动器,给用户一种启动活动和返回的任务创建后任何时间启动。


这第二个能力是很重要的:用户必须能够留下一个任务然后回来后使用此活动发射器。因为这个原因,两种启动模式,马克活动一如既往地开始一项任务,singleTasksingleInstance,应该使用只有当活动有一个ACTION_MAINaCATEGORY_LAUNCHER过滤器。例如,想象会发生什么,如果缺少过滤:一个意图启动一个singleTask活动,启动一个新任务,用户花一些时间在这个任务工作。然后用户按下按钮。现在的任务是发送到背景和不可见。现在用户已经没有办法回到任务,因为它不是代表应用程序启动器。


对于那些情况下,您不希望用户能够回到一个活动,设置<活动>元素'sfinishOnTaskLaunchtrue(见清理堆栈)