(声明:本系列博客不讲述经常用到的知识点,比如关于关于Activity的生命周期介绍及其转换等,而是记录一些应用开发中不太常用但却在高级或者更底层的开发中可能会用到的点。系列文章会根据本人的不断学习不定时更新,内容来自于本人相关书籍的学习和网络资料的理解。)
首先,复习一下Android应用进程的基础知识:
谷歌为Android系统定制的虚拟机,叫做Dalvik,Android系统支持同时运行多个虚拟机实例。每个Android应用程序都在自己的进程中运行,它们都拥有一个独立的Dalvik虚拟机实例。每个应用程序都有自己的名字,可以再Android配置文件AndroidManifest.xml文件中,修改<aplication/>节点的android:process属性进行设置。通常情况下,不需要设置,因为每个Android应用都会有一个专属的包名,此包名用来区分应用程序。
Android是基于Linux内核的,它的进程运行方式可以参考Linux的进程。
需要注意的是:
一般情况下两个不同的Android应用程序各自运行在其独立的应用程序运行空间(我们称之为沙箱)中,它们拥有不同的Linux用户ID。
那么,如果需要共享几个应用程序之间的数据和资源(共享非常频繁),也可以给这些应用程序分配相同的Linux用户ID,于是它们就运行在一个进程中,共享一个虚拟机,从而更高效的使用系统资源。
实现:首先在Android工程配置文件AndroidManifest.xml中修改manifest节点的android:sharedUserId属性,给几个不同应用程序设置相同的Linux用户ID,然后在应用程序打包时,使用相同的私钥签署这些应用程序;
例如,Android系统中的应用程序Launcher和Contacts就设置了同样的sharedUserId,xml代码如下:
Launcher中:
<manifest xmlns:android="http://......."
package="com.android.launcher"
android:sharedUserId="android.uid.shared"
android:sharedUserLabel="@string/application_name>
<!--省略部分内容 -->
</manifest>
而在Contacts中与上面相同,除了package行变为"com.android.contacts"
ActivityThread运行框架:
在Android系统框架中,andoid.app.Applicatin类并不代表应用程序进程,它实际上是应用程序的上下文环境,而ActivityThread类才真正代表应用程序进程。(这一点,可以在Android应用程序调试模式中的堆栈信息得到证明)
每个应用程序都是以ActivityThread.main()为入口,执行Looper类的loop()方法后进入到消息循环(是个死循环).
(1)Activity Manager Service创建应用程序进程,保存进程ID和名称。
(2)启动应用程序进程并建立通信通道:应用进程使用thread.attach()向Activity Manager Service发起请求来与Activity Manager Service建立双向连接。后者可以使用IActivityThread接口访问应用程序对象。
那么应用程序进程是何时启动的,系统消息如何传递,Activity如何实例化,其实例又是如何与应用程序进程关联?
我们看ActivityThread类的源码摘要:
public final class ActivityThread {
final ArrayMap<IBinder, ActivityClientRecord> mActivities
= new ArrayMap<IBinder, ActivityClientRecord>();
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
}
final void performRestartActivity(IBinder token) {
}
public final ActivityClientRecord performResumeActivity(IBinder token,
boolean clearHide) {
}
final Bundle performPauseActivity(IBinder token, boolean finished,
boolean saveState) {
}
final void performStopActivity(IBinder token, boolean saveState) {
}
private void performStopActivityInner(ActivityClientRecord r,
StopInfo info, boolean keepShown, boolean saveState) {
}
public final ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing) {
return performDestroyActivity(token, finishing, 0, false);
}
我们看到,应用程序进程中的Activity都被放在mActivities数组中。这些ActivityRecord记录了应用程序的所有Activity子类的实例。为了方便管理,Activity管理服务内核中保留了一些活动,称为HistoryRecord,它是activity栈的核心组成部分。
所以,在Android系统框架中,Activity实际上有两个实体,一个是负责与用户交互的活动,另一个是活动管理服务的HistoryRecord(放在mHistory栈中,栈顶的活动就是用户当前看到的活动)。
活动的内核实体依附在ProcessRecord成员变量中,通过IActivityThread接口可以访问到它对应的Activity方法。在LaunchActivity时,活动管理服务将对应的HistoryRecord作为token传递到客服端与活动建立联系。