Activity调度机制
Activity调度机制
在Android中,Activity调度的基本思路是这样的:各应用进程要启动新的Activity或者停止当前的Activity,都要首先报告给AmS,而不能“擅自处理”。AmS在内部为所有应用进程都做了记录,当AmS接到启动或停止的报告时,首先更新内部记录,然后再通知相应客户进程运行或者停止指定的Activity。由于AmS内部有所有Activity的记录,也就理所当然地能够调度这些Activity,并根据Activity和系统内存的状态自动杀死后台的Activity。
具体来讲,启动一个Activity有以下几种方式。
— 在应用程序中调用startActivity()启动指定的Activity。
— 在Home程序中单击一个应用图标,启动新的Activity。
— 按“Back”键,结束当前Activity,自动启动上一个Activity。
— 长按“Home”键,显示出当前任务列表,从中选择一个启动。
这四种启动方式的主体处理流程都会按照第一种启动方式运行,后面三种方式只是在前端消息处理上各有不同,因此,后面首先介绍第一种启动方式,然后介绍其他启动方式的前端处理差异。
AmS中定义了几个重要的数据类,分别用来保存进程(Process)、活动(Activity)和任务(Task)。
1.进程数据类ProcessRecord
该类在framework/base/services/java/com/android/server/am/路径下,该路径最后的am代表Activity Manager,和AmS有关的重要类都在该目录下。
一个APK文件运行时会对应一个进程,当然,多个APK文件也可以运行在同一个进程中。ProcessRecord正是记录一个进程中的相关信息,该类中内部变量可分为三个部分,大家先不用琢磨具体某个变量如何被使用,而只需要先了解它们的作用。这三个部分如表10-1所示。
2.HistoryRecord数据类
AmS中使用HistoryRecord数据类来保存每个Activity的信息,有些读者可能奇怪,Activity本身也是一个类啊,为什么还要用HistoryRecord来保存Activity的信息,而不直接使用Activity呢?因为,Activity是具体的功能类,这就好比每一个读者都是一个Activity,而“学校”要为每一个读者建立一个档案,这些档案中并不包含每个读者具体的学习能力,而只是学生的籍贯信息、姓名、出生年月、家庭关系等。HistoryRecord正是AmS为每一个Activity建立的档案,该数据类中的变量主要包含两部分,如表10-2所示。
需要注意,HistoryRecord类也是一个Binder,它基于IApplicationToken.Stub类,因此,可以被IPC调用,一般是在WmS中进行该对象的IPC调用。
3.TaskRecord类
AmS中使用任务的概念确保Activity启动和退出的顺序。比如以下启动流程,A、B、C分别代表三个应用程序,数字1、2、3分别代表该应用中的Activity。
A1→A2→A3→B1→B2→C1→C2,此时应该处于C2,如果AmS中没有任务的概念,此时又要从C2启动B1,那么会存在以下两个问题:
— 虽然程序上是要启动B1,但是用户可能期望启动B2,因为B1和B2是两个关联的Activity,并且B2已经运行于B1之后。如何提供给程序员一种选择,虽然指定启动B1,但如果B2已经运行,那么就启动B2。
— 假设已经成功从C2跳转到B2,此时如果用户按“Back”键,是应该回到B1呢,还是应该回到C2?
任务概念的引入正是为了解决以上两个问题,HistoryRecord中包含一个int task变量,保存该Activity所属哪个任务,程序员可以使用Intent.FLAG_NEW_TASK标识告诉AmS为启动的Activity重新创建一个Task。
有了Task的概念后,以上情况将会是这样的:
虽然程序明确指定从C2启动到B1,程序员可以在intent的FLAG中添加NEW_TASK标识,从而使得AmS会判断B1是否已经在mHistory中。如果在,则找到B1所在的Task,并从该Task中的最上面的Activity处运行,此处也就是B2。当然,如果程序的确要启动B1,那么就不要使用NEW_TASk标识,使用的话,mHistory中会有两个B1记录,隶属于不同的Task。
TaskRecord类中的变量如表10-3所示。
需要注意的是,TaskRecord中并没有该任务中所包含的Activity列表,比如ArrayList<HistoryRecord>或者HistoryRecord[]之类的变量,这意味着不能直接通过任务id找到其所包含的Activity。要达到这个目的,可以遍历AmS中mHistory中的全部HistroyRecord,然后根据每一个HistoryRecord中的TaskRecord task变量确定是否属于指定的任务。
本文选自《Android内核剖析 》一书
图书详细信息:http://www.cnblogs.com/broadview/archive/2011/09/23/2186439.html