Android SDK 1.5中文版 (Application基础—3) 对于用户而言,这看起来就像是地图浏览器是我们的Activity所在的应用程序中的组成部分,尽管它是由其他应用程序定义,并运行在那个应用程序的进程之中。Android将这两个Activity放在同一个任务中来维持一个完整的用户体验。简单的说,任务就是用户所体验到的“应用程序”。它是安排在一个堆栈中的一组相关的Activity。堆栈中的根Activity就是启动任务的Activity——通常,它就是用户在应用程序加载器中所选择Activity。而堆栈最上方的Activity则是当前运行的——直接响应用户操作。当一个Activity启动另外一个的时候,新的Activity就被压入堆栈,并成为当前运行的Activity。而前一个Activity仍保持在堆栈之中。当用户按下BACK键的时候,当前Activity出栈,而前一个恢复为当前运行的Activity。 堆栈中保存的其实是对象,所以如果堆栈有相同Activity之类的多个实例(例如多个地图浏览器),堆栈会独立保存每个实例。堆栈中的Activity永远不会重新排列,只有压栈和出栈。 任务其实就是Activity的堆栈,而不是manifest文件中的一个类或者元素。所以我们无法撇开Activity而为一个任务设置一个值。而事实上整个任务使用的值是在根Activity中设置的。例如,下一节我们会谈及“任务的Affinity”,这个值就是根Activity的Affinity设置中读出。 任务中的所有Activity是作为一个整体进行移动的。整个任务(整个Activity堆栈)可以移到前台,或退至后台。例如,设想当前任务堆栈中存有四个Activity——三个在当前Activity之后。当用户按下HOME键回到应用程序加载器,然后选择一个新的应用程序(事实上是一个新任务)。则当前任务进入后台,而新任务的根Activity显示出来。然后,用户很快再次回到应用程序加载器而又选择了前一个应用程序(前一个任务)。于是前面的任务,包括堆栈中所有的四个Activity,再次回到前台。当用户按下BACK键的时候,屏幕不会显示出用户刚才离开的Activity(上一个任务的根Activity)。取而代之,当前任务堆栈中最上面的Activity被弹出,而同一任务中的上一个Activity被显示出来。 上述行为都是Activity和任务的默认行为。但是有方法可以改变所有这一切。Activity和任务的联系、任务中Activity 的行为方式,都是由启动Activity的Intent对象中设置的一系列标记和manifest文件中对应Activity中的<activity>元素的系列属性相互协作进行控制。请求发出者和回应者在这里都拥有话语权。 我们刚才所说的关键Intent标记如下: FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_CLEAR_TOP FLAG_ACTIVITY_RESET_TASK_IF_NEEDED FLAG_ACTIVITY_SINGLE_TOP 而主要的<activity>属性是: taskAffinity launchMode allowTaskReparenting clearTaskOnLaunch alwaysRetainTaskState finishOnTaskLaunch 接下来的一节会描述这些标记以及属性的作用,它们是如何互相影响的,以及使用它们的时候必须考虑的因素。 1.2.1 Affinity(亲缘性)和新任务 FLAG_ACTIVITY_NEW_TASK标记 allowTaskReparenting 属性 如果一个.apk文件中包含了多个用户视觉看到的“应用程序”,我们可能需要为相关的Activity赋予不同的Affinity。 1.2.2 启动模式 “standard”(默认值) “singleTop” “singleTask” “singleInstance” 这些模式之间的差异主要体现在四个方面: 哪个任务会保留对Intent做出响应的Activity。对于“standard”和“singleTop”模式,是生成Intent(并调用 startActivity())的任务——除非Intent对象包含FLAG_ACTIVITY_NEW_TASK标记。如果设定了该值,正如前一节Affinitie和新任务所述,会选择不同的任务。相反,对于“singleTask”和“singleInstance”模式,Activity总是位于任务的根部。正是它们定义了一个任务,所以它们绝不会被加载到其它任务之中。 另一方面,如果新到达的Intent是针对B类型的Activity,则无论B的模式是“standard”还是“singleTop”,都会加载一个新的B实例(因为B不位于堆栈的顶部),而堆栈的顺序变为A-B-C-D-B。 如前所述,“singleTask”或“singleInstance”模式的Activity永远不会存在多个实例。所以该实例将处理所有的新Intent。“singleInstance”模式的Activity永远保持在堆栈的顶部(因为它是堆栈中唯一的Activity),因此它一直位于该处理Intent的位置。但是,对于“singleTask”模式的Activity,它的任务堆栈上面可能有,也可能没有其他的Activity。如果有,它就不在能够处理Intent的位置上,则那个Intent被抛弃。(即便在Intent被抛弃的情况下,它的到底仍将使这个任务切换至前台并一直保留。) 当现有的Activity被要求处理新的Intent时,会调用他的onNewIntent()方法并将Intent对象传入。(原始启动Activity的Intent对象可以通过调用getIntent()方法获得。) 请注意,当创建一个新的Activity实例来处理新的Intent时,用户总是可以按下BACK键来回到前面的状态(回到前一个 Activity)。但是当使用现有的Activity来处理新Intent的时候,用户是不能靠按下BACK键回到当这个新Intent抵达之前的状态的。 关于启动模式的更多信息,请参阅AndroidManifest.xml文件。 1.2.3 清理堆栈 这些属于默认行为,当然也有一些Activity属性来控制并改变这些行为: alwaysRetainTaskState 属性 clearTaskOnLaunch属性 inishOnTaskLaunch属性 还有另外一种方法将Activity从堆栈中强制移除。如果Intent对象包含FLAG_ACTIVITY_CLEAR_TOP标记,而且目标任务的堆栈中已经存在了一个能够响应此Intent的Activity类型的实例,则这个实例之上的所有Activity都将被清理以使它位于堆栈的顶部来响应Intent。如果指定的Activity的启动模式为“standard”,则它本身也会从堆栈中移除,并启动一个新的实例来处理新的Intent。这是因为加载模式为“standard”的Activity总会创建一个新实例来处理新的Intent。 FLAG_ACTIVITY_CLEAR_TOP与FLAG_ACTIVITY_NEW_TASK经常合并使用。这时,这些标记提供了一种方法:定位其它任务中现存的Activity、并将它们置于可以对Intent做出响应的位置。 1.2.4 启动任务 第二个功能相当重要:用户必须可以离开一个任务,并在一段时间后返回它。出于这个考虑,总是会初始化一个新任务的启动模式“singleTask”和“singleInstance”,这两种模式仅能用于指定了MAIN和LAUNCHER过滤器的Activity。例如,如果没指定这样的过滤器将会发生什么呢:用Intent启动了一个“singleTask”的Activity,初始化了一个新任务,用户在这个任务中花费了一些时间来完成工作。然后用户按下HOME键。该任务切换至后台并被主屏幕所覆盖。由于它并没有在应用程序加载器中显示图标,这将导致用户再也无法回到它。 FLAG_ACTIVITY_NEW_TASK标记也可能引起类似的问题。如果此标记使一个Activity启动了一个新任务继而用户按下了HOME键离开了它,则用户必须要有一些方法再次回到这个任务。一些实体(比如通知管理器)总是在外部任务中启动新的Activity,而不是做为它们自己的一部分,所以它们总是将FLAG_ACTIVITY_NEW_TASK标记包含在Intent里面并传递给startActivity()。如果写了一个能被外部实体使用这个标记调用的Activity,我们必须注意要给用户留一个返回这个被外部实体启动的任务的方法。 当不希望让用户再次返回一个Activity时,可以将<activity>元素的finishOnTaskLaunch设置为“true”。参考前面的清理堆栈。 转自:http://blog.youkuaiyun.com/laiyiling/archive/2009/08/22/4474058.aspx
|