Android Activity 和任务

如前所述,一个activity 可以启动另外一个,甚至包括与它不处于同一应用程序之中的。

举个例子说,假设你想让用户看到某个地方的街道地图。

而已经存在一个具有此功能的activity 了,那么你的activity 所需要做的工作就是把请求信息放到一个Intent 对象里面,并把它传递给startActivity()。于是地图浏览器就会显示那个地图。

而当用户按下BACK 键的时候,你的activity 又会再一次的显示在屏幕上。

对于用户来说,这看起来就像是地图浏览器是你activity 所在的应用程序中的一个组成部分,其实它是在另外一个应用程序中定义,并运行在那个应用程序的进程之中的。

Android 将这两个activity 放在同一个任务中来维持一个完整的用户体验。

简单的说,任务就是用户所体验到的“应用程序”。它是安排在一个堆栈中的一组相关的activity。

堆栈中的根activity 就是启动了这整个任务的那个──一般情况下,它就是用户在应用程序加载器中所选择的。

而堆栈最上方的activity 则是当前运行的──用户直接对其进行操作的。

当一个activity 启动另外一个的时候,新的activity 就被压入堆栈,并成为当前运行的activity。

而前一个activity 仍保持在堆栈之中。当用户按下BACK 键的时候,当前activity 出栈,而前一个恢复为当前运行的activity。

堆栈中保存的其实是对象,所以如果发生了诸如需要多个地图浏览器的情况,就会使得一个任务中出现多个同一Activity 子类的实例同时存在,堆栈会为每个实例单独开辟一个入口。堆栈中的Activity 永远不会重排,只会压入或弹出。

任务其实就是activity 的堆栈,而不是manifest 文件中的一个类或者元素。所以你无法撇开activity 而为一个任务设置一个值。而事实上整个任务使用的值是在根activity 中设置的。

任务中的所有activity 是作为一个整体进行移动的。整个的任务(即activity 堆栈)可以移到前台,或退至后台。

举个例子说,比如当前任务在堆栈中存有四个activity──三个在当前activity 之下。

当用户按下 HOME 键的时候,回到了应用程序加载器,然后选择了一个新的应用程序(也就是一个新任务)。

则当前任务遁入后台,而新任务的根activity 显示出来。

然后,过了一小会儿,用户再次回到了应用程序加载器而又选择了前一个应用程序(上一个任务)。于是那个任务,带着它堆栈中所有的四个activity,再一次的到了前台。

当用户按下BACK 键的时候,屏幕不会显示出用户刚才离开的activity(上一个任务的根activity)。

取而代之,当前任务的堆栈中最上面的activity 被弹出,而同一任务中的上一个activity 显示了出来。

上述的种种即是activity 和任务的默认行为模式。但是有一些方法可以改变所有这一切。

activity 和任务的联系、任务中activity的行为方式都被启动那个activity的Intent 对象中设置的一系列标记和manifest 文件中那个activity 中的元素的系列属性之间的交互所控制。

无论是请求发出者和回应者在这里都拥有话语权。

我们刚才所说的这些关键Intent 标记如下:

FLAG_ACTIVITY_NEW_TASK

FLAG_ACTIVITY_CLEAR_TOP

FLAG_ACTIVITY_RESET_TASK_IF_NEEDED

FLAG_ACTIVITY_SINGLE_TOP

而关键的属性是:
taskAffinity

launchMode

allowTaskReparenting

clearTaskOnLaunch

alwaysRetainTaskState

finishOnTaskLaunch