一、概述
Activity是Android应用程序用户界面的基本组件,它与Service、ContentProvider、Broadcast Receiver被称为Android应用程序的四大核心组件。从应用程序结构层次上来说,每个Android应用是Application类的一个实例,每个Android应用可以包含多个Activity实例。一个Activity实例代表应用程序窗口(Window)组件,它本身并不提供用户界面,它是所有UI控件依附的容器。Activity可以获得焦点、接收用户事件,并把事件分发给内部的UI控件处理来完成整个交互过程。
Android应用程序通常都是由很多Activity组成,一个应用从开始运行到运行结束构成了Android应用程序的生命周期。在Android系统框架中Application实际上代表了应用程序的上下文环境,Activity才是重要的表现者,一个完整的应用程序的生命周期通常由许多Acitivity的生命周期构成。
Android应用程序在运行时,系统都会为它分配一个独立的虚拟机进程,每个应用程序都运行在独立的进程空间。Android系统是基于Linux操作系统的,所以Android的进程概念与Linux操作系统的进程概念相同。Android应用程序一般由Activity、Service、ContentProvider、Broadcast Receiver 等组件构成,这些组件的运行过程都需要依附于Linux 进程。
对于进程来说,如果要让它常驻内存为其他组件提供服务,必须要建立一个闭合的消息循环(死循环)。对于Android应用程序来说,应用程序进程启动之后也开启了一个闭合消息循环,然后把组件依附在进程之上。
理解Android中Activity的架构设计,以及Android应用把Activity组件依附到linux进程的过程,可以从以下三个方面入手:
二、
应用程序进程空间
Dalvik是Google为Android系统定制的虚拟机,Android系统支持同时运行多个虚拟机实例,每个Android应用程序都在自己的进程中运行,它们都拥有一个独立的Dalvik虚拟机实例。
每个应用程序进程都有各自的进程名字,可以在Android工程的AndroidManifest.xml文件中,修改 <application />节点的android:process属性设置应用程序进程的名称,通常情况都不需要设置这个属性,因为每个Android应用都会有一个不同于其他应用的包名, Android系统会使用应用程序的包名作为应用程序进程的名字。
一个Android应用通常由多个Activity组成,其中有一个“主Activity”为应用启动时第一个显示的Activity。Activity Manager Service 在应用程序的第一个组件需要运行时将会为应用程序建立一个进程,而这个进程的名字就是由android:process=”string”指定,默认情况是应用程序的包名,建立进程之后所有组件都将运行在该进程中。在加载第一个Actvitiy 时,如果应用程序还没有创建Application对象,应用程序会首先建立一个Application 对象,并初始化应用程序上下文。
当应用程序被安装到设备上时,Android系统会为每个应用程序分配一个Linux用户ID,并设置相应的资源访问权限,这样应用程序之间就不能相互访问各自拥有的数据和资源。在Linux系统中,一个用户ID对应一个特定的用户,在Android系统中,一个用户ID对应一个特定应用程序。只要应用程序没有被卸载,Android系统为应用程序分配的Linux用户 ID会保持不变。
默认情况下,每个应用程序运行在它自己的Linux进程中。当应用程序启动时,Android系统的虚拟机孵化器会为这个应用程序启动一个新虚拟机进程,因此不同的应用程序是运行在相互隔离的虚拟机进程中。
如下图所示:
图1 应用程序运行在独立的进程空间
如果需要共享几个应用程序之间的数据和资源,也可以给这些应用程序分配相同的Linux用户ID,这样多个应用程序之间就能相互访问各自所拥有的资源。Android系统把具有相同Linux用户ID的应用程序,运行在同一个进程中共享同一个虚拟机,这样能够更高效地使用系统资源。如果要实现不同的应用程序运行在相同的进程中,通过修改<manifest />节点的android:sharedUserId属性,给几个不同的应用程序设置相同的 Linux 用户 ID,然后必须在应用程序打包时,使用相同的私钥签署这些应用程序。Android系统中的应用程序Launcher和Contacts就设置了同样的sharedUserId。
图2 不同应用程序运行在相同进程空间
三、
ActivityThread 运行框架
在Android系统框架中,android.app.Application类并不是代表应用程序进程,它实际上代表了应用程序的上下文环境,而ActivityThread类才是真正的代表应用程序进程。
每个应用程序都以ActivityThread.main()为入口,执行Looper类的loop()方法后进入到消息循环。对于Android应用进程来说非常需要像这样闭合的处理框架。ActivitiyThread是应用程序进程空间的重要概念,它建立了应用进程运行的框架,并提供了一个IActivityThread 接口与Activity Manager Service通讯。通过IActivityThread接口Activity Manager Service可以将Activity 的状态变化传递到客户端的Activity对象。
Actvitiy Manager Service与应用进程的绑定分为两步,第一部分就是Actvitiy Manager Service建立应用程序进程,第二部分是应用程序进程绑定到Actvitiy Manager Service并与Actvitiy Manager Service建立通讯通道。这部分就不再展开讲解了,只需了解应用进程与Actvitiy Manager Service的绑定。
图3 ActivityThread 运行框架
四、Activity加载过程
对于Activity Manager Service来说Activity就是对应的客服端。在编写Android 应用程序时,需要扩展Android 系统框架中的Activity类,在子类中实现Activity类提供的一些与生命周期相关的方法:void onCreate(Bundle savedInstanceState)、void onRestart()、void onStart()、void onResume()、void onPause()、void onStop()、void onDestroy()等。
在定义Activity的子类并实现了一些与生命周期相关的方法之后,其他的操作都由Android系统后框架完成,这对于Android应用开发者来说都是透明的,也就是应用开发者无需关心Android系统对Activity的调度过程。
上面的内容已经说到 Android应用程序进程对应的类就是ActivityThread类,Activity的加载和调度的过程都是通过ActivityThread类完成的。
从ActivityThread源码中可以看出,在应用程序进程中的Activity 都被放置在mActivities 数组中。这些ActivityRecord记录了应用程序进程中所有Activity子类的实例。每个Activity子类实例代表应用程序端与用户交互的Activity。为了方便管理这些Activity,Activity Manager Service内核中也保留了一些对应的Activity,被称为HistoryRecord,它是activity栈的核心组成部分。
在Android系统框架中Activity 实际上有两个实体。一个在应用进程中与负责与用户交互的Activity,另外一个是在Activity Manager Service中具有管理功能的History Record。应用进程中的Activity 都记录在ActivityThread实例中的mActivity 数组中,而Activity Manager Service中的HistroytRecord 实例放置在mHistroy 栈中。mHistory 栈是Android 管理Activity 的场所,处于栈顶的Activity就是用户看到的当前处于活动状态的Activity。
Activity 的内核实体是依附在ProcessRecord 的成员变量中,通过ProcessRecord 可以访问到所有属于该Process 的Activity。通过IActivtityThread接口,可以访问到它对应的Activity 的方法。在LaunchActivity 时,Activity Manager Service将对应的HistoryRecord 作为token 传递到客服端与客服端的Activity 建立联系。当Activity Manager Service中的Activity 状态变化时,Activity Manager Service找到客服端的Activity,从而将消息或者动作传递应用程序中对应的Activity 。
图4 ActivityThread管理acitivity的内部结构图