10.3.2 创建ActivityThread对象

当AThread成功创建ActivityManagerService并进入第一次等待状态后,main方法结束第二次等待状态,开始执行ActivityThread的systemMain方法。ActivityThread定义于frameworks/base/core/java/android/app/ActivityThread.java,代码如下:


public static ActivityThread systemMain(){

HardwareRenderer.disable(true);//在当前进程中禁止硬件渲染

/新建一个ActivityThread类型的对象,其构造函数的函数体为空/

ActivityThread thread=new ActivityThread();

thread.attach(true);//执行attach方法,传入参数true

return thread;

}


systemMain()方法首先创建一个ActivityThread类型的thread对象,该对象返回后被保存到ActivityManagerService的mSystemThread成员变量中;然后调用thread的attach方法,传入参数为true。

注意 ActivityThread是Android框架层最重要的类之一,其官方解释如下:

ActivityThread负责管理应用程序所在进程的主线程(UI线程)的执行、调度和运行activities、broadcasts以及执行Activity Manager请求的其他操作。

当然,这个解释还不能涵盖ActivityThread的所有功能。这里读者只需要了解这个类的概念,明白这里创建了一个与应用程序主线程关联的ActivityThread对象即可。本书会在以后的章节中不断深化对该类的分析。

ActivityThread的构造方法中没有执行任何操作,接下来分析systemMain方法中一个关键步骤:调用attach(true)方法,其代码如下:


public final class ActivityThread{

……

Application mInitialApplication;

final ArrayList<Application>mAllApplications=new ArrayList<Application>();

Instrumentation mInstrumentation;

……

private void attach(boolean system){

sThreadLocal.set(this);//ActivityThread是线程独立的

mSystemThread=system;//根据传入的参数,此处为true,判断是否位于系统进程

if(!system){//普通应用程序,此处不执行这个分支

……

}else{

/*设置应用进程名为system_process。如果此时DDMS连接到设备,会

通知DDMS显示system_server的进程名为system_process/

android.ddm.DdmHandleAppName.setAppName("system_process");

try{

//创建Instrumentation

mInstrumentation=new Instrumentation();

/①构造ContextImpl类型的对象,并通过init方法初始化/

ContextImpl context=new ContextImpl();

//初始化,第一次出现

context.init(getSystemContext().mPackageInfo, null, this);

/②借助Instrumentation生成Application类型的对象/

Application app=Instrumentation.newApplication(

Application.class, context);

//一个ActivityThread可以对应多个Application

mAllApplications.add(app);

mInitialApplication=app;

app.onCreate();//调用Application的onCreate方法

}catch(Exception e){

}

}

//当Configuration发生变化时的回调处理函数

ViewRootImpl.addConfigCallback(new ComponentCallbacks2(){

public void onConfigurationChanged(Configuration newConfig){

……

}

public void onLowMemory(){

}

public void onTrimMemory(int level){

}

});

}


attach方法会区分系统进程或非系统进程分别调用不同的处理流程,本例中传入attach方法的参数为true,即系统进程。zygote、system_server以及在AndroidManifest.xml中声明了android:sharedUserId="android.uid.system"的APK(frameworks-res.apk、SettingsProvider.apk、InputDevices.apk等)都可视为系统进程。

这里涉及Android框架层几个重要的类,包话:Instrumentation、Context、ContextImpl、Application。这几个类的功能和结构比较复杂,有必要先对它们有一个概念上的认识。

Instrumentation[1]:应用程序测量工具的基类。当运行时Instrumentation开启时,该类先于应用程序代码被初始化,用于监控系统与应用程序之间的交互。开发者可以在AndroidManifest.xml文件的instrumentation标签中指定Instrumentation的一个具体实现类。可见Instrumentation与AndroidManifest.xml文件的instrumentation标签是等价的。

ContextImpl[2]:Context的通用实现类,为Activity和其他应用程序组件提供一个基本的Context对象。可见ContextImpl是Context的子类。

Context2[3]:一个可以获取应用程序运行环境中的一些全局信息的接口(这里的接口是广义的概念,Context本身是一个Java抽象类,而非Java中的Interface)。Context本身是一个抽象类,其实现类需要由系统提供(该实现类便是ContextImpl)。通过这个接口,开发者可以访问应用层面的资源和类,还可以调用一些操作应用程序组件的方法。

Application[4]:一个可以维护全局的应用程序状态的基类。开发者可以通过在AndroidManifest.xml的application标签中指定它的一个实现类来使用这项功能。被指定的实现类,将会在应用程序进程创建的时候实例化。可见Application与AndroidManifest.xml的application标签是等价的。

attach方法执行的主要步骤以①②标出,接下来详细分析这两个主要步骤。

1.系统Context的创建和初始化

系统Context的创建和初始化在①中完成。其中Context由ContextImpl默认构造函数创建,然后通过ContextImpl的init方法将其初始化为系统Context。系统Context的创建和初始化过程是糅合在一起的,并且经历了多次初始化,接下来详细分析这个过程。

ContextImpl在默认构造函数中,仅仅是把this引用赋值给成员变量mOuterContext,此时该ContextImpl还不是一个系统Context,接下来需要调用getSystemContext方法,代码如下:


public ContextImpl getSystemContext(){

synchronized(this){//同步代码保证单例的创建

if(mSystemContext==null){

//创建系统Context

ContextImpl context=ContextImpl.createSystemContext(this);

//创建包名为android的APK对应的LoadedApk对象

LoadedApk info=new LoadedApk(this,"android",context, null,

CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO);

//初始化,第二次出现

context.init(info, null, this);

//更新资源配置信息

context.getResources().updateConfiguration(

getConfiguration(),getDisplayMetricsLocked(

CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, false));

mSystemContext=context;//保存到成员变量中

}

}

return mSystemContext;

}


可见getSystemContext()方法的主要工作是创建一个单例的系统Context对象,并对其初始化。

(1)第一次初始化:ContextImpl对象

首先分析createSystemContext方法,该方法的工作是创建一个ContextImpl对象,并对其初始化,代码如下:


static ContextImpl createSystemContext(ActivityThread mainThread){

//新建一个ContextImpl对象,将自身存入内部成员变量mOuterContext中

ContextImpl context=new ContextImpl();

/*Resources.getSystem()返回一个可以访问frameworks中定义的系统资源的

Resource对象,然后以该对象初始化context对象/

context.init(Resources.getSystem(),mainThread);//初始化,第三次出现

return context;

}


该初始化过程是第三次出现,第一次执行。首先,创建ContextImpl对象是在默认构造函数ContextImpl()中完成的,并将当前对象赋值到成员变量mOutContext中;然后,通过Resources.getSystem()方法获取框架层系统资源的引用,并以其为参数调用init(Resources resources, ActivityThread mainThread)方法。

传入init的参数resources将为ContextImpl对象的mResources成员变量赋值,此时便可以通过ContextImpl访问到系统Resource。传入的mainThread参数首先为ContextImpl对象的mMainThread成员变量赋值,然后构造一个ApplicationContentResolver类型的对象初始化mContentResolver成员变量。ApplicationContentResolver是ContentResolver的子类,用于访问Content Provider。

综上所述,createSystemContext的作用是提供了利用Context访问框架层系统资源和Content Provider共享资源的接口。

(2)第二次初始化:LoadedApk对象

createSystemContext执行完毕后返回到getSystemContext方法,接下来分析LoadedApk的创建过程。LoadedApk记录了当前所加载APK的信息,其构造函数的代码如下:


public LoadedApk(ActivityThread activityThread, String name,

Context systemContext, ApplicationInfo info,

CompatibilityInfo compatInfo){

mActivityThread=activityThread;//关联到当前ActivityThread

mApplicationInfo=info!=null?info:new ApplicationInfo();

mApplicationInfo.packageName=name;//记录包信息

mPackageName=name;

mAppDir=null;

mResDir=null;

mSharedLibraries=null;

mDataDir=null;

mDataDirFile=null;

mLibDir=null;

mBaseClassLoader=null;

mSecurityViolation=false;

mIncludeCode=true;

mClassLoader=systemContext.getClassLoader();

mResources=systemContext.getResources();//关联系统资源

mCompatibilityInfo.set(compatInfo);

}


可见在LoadedApk的构造函数中,通过mActivityThread成员变量关联当前ActivityThread;通过mApplicationInfo成员变量关联当前APK的ApplicationInfo(即framework-res.apk),并将包名android存入mApplicationInfo的mPackageName成员变量;通过系统context将系统Resource关联到mResources成员变量;最后一个参数则用于指定兼容模式信息。

LoadedApk创建成功后,执行系统Context的第二次初始化,init(info, null, this)方法会调用其重载方法init(packageInfo, null, this, null, null),代码如下:


final void init(LoadedApk packageInfo, IBinder activityToken,

ActivityThread mainThread,

Resources container, String basePackageName){

mPackageInfo=packageInfo;//即上一步的LoadedApk对象

//mBasePackageName赋值为android

mBasePackageName=basePackageName!=null?

basePackageName:packageInfo.mPackageName;

mResources=mPackageInfo.getResources(mainThread);

……//省略不被执行的代码

mMainThread=mainThread;

mContentResolver=new ApplicationContentResolver(this, mainThread);

//这里只是给成员变量mActivityToken赋值,此时赋值为null

setActivityToken(activityToken);

}


可见第二次初始化的主要工作是将LoadedApk关联到系统Context。LoadedApk存入ContextImpl的mPackageInfo成员变量;ActivityThread存入ContextImpl的mMainThread成员变量;ApplicationContentResolver存入ContextImpl的mContentResolver。此后,开发人员便可以通过ContextImpl提供的接口访问这些信息。

(3)第三次初始化:系统Context

第二次初始化完成后,将系统Context存入ActivityThread的mSystemContext成员变量,getSystemContext方法便执行完毕,并返回到ActivityThread的attach方法。在attach方法中,首先从mSystemContext中获取第二次初始化时创建的系统Context,进而执行第三次初始化过程,代码如下:


context.init(getSystemContext().mPackageInfo, null, this);


第三次初始化使用的第一个参数便是第二次初始化时创建的LoadedApk,因此其与第二次初始化并无本质区别。

可见创建和初始化系统Context的代码十分繁琐,而且创建了大量临时对象。系统Context的创建和初始化过程建立的类图结构如图10-2所示。

10.3.2 创建ActivityThread对象 - 图1

图 10-2 系统Context的创建和初始化过程

ContextImpl继承自Context,通过多次init调用使其成为系统Context,该系统Context建立了与Resource、LoadedApk、ActivityThread、ApplicationContentResolver的关联关系。Resource代表系统资源的引用,LoadedApk代表frameworks-res.apk的相关信息,ActivityThread代表当前应用程序线程(因为system_server中运行了frameworks-res.apk,因此需要一个ActivityThread对象与之对应),ApplicationContentProvider继承自ContentResolver,用于访问Content Provider提供的共享资源。

2.创建Application对象

系统Context创建完毕后,进入attach方法步骤②:创建Application对象。Instrumentation定义于frameworks/base/core/java/android/app/Instrumentation.java中,其实现代码如下:


//参数clazz赋值为Application.class, context即系统Context

static public Application newApplication(Class<?>clazz, Context context)

throws InstantiationException, IllegalAccessException,

ClassNotFoundException{

//通过Java反射机制创建Application

Application app=(Application)clazz.newInstance();

app.attach(context);//将Application和系统Context关联

return app;

}


可见newApplication方法创建Application并将其与系统Context关联到一起,其代码如下:


/package/final void attach(Context context){

attachBaseContext(context);//调用父类方法

//获取系统Context中关联的LoadedApk并将其关联到自身内部

mLoadedApk=ContextImpl.getImpl(context).mPackageInfo;

}


Application继承自ContextWrapper,在attach方法中首先调用attachBaseContext,将系统Context存入ContextWrapper.mBase成员变量中,然后读取系统Context中存储的LoadedApk,并将其存入Application.mLoadedApk成员变量中。

Application的类图结构如图10-3所示。

10.3.2 创建ActivityThread对象 - 图2

图 10-3 Application的类图结构

ContextWrapper和ContextImpl都是Context的子类。ContextWrapper的成员变量mBase引用一个Context类型的对象,ContextWrapper中定义的所有方法都间接调用了Context中的相应方法,因此ContextWrapper不仅是Context的子类,同时还是封装了Context的工具类。以系统Context为参数调用Application.attach方法时,在该方法内部通过attachBaseContext方法将系统Context存入ContextWrapper.mBase中,因此ContextWrapper通过mBase关联了ContextImpl。

Application创建完毕后,返回到ActivityThread的attach方法,将该Application添加到ActivityThread.mAllApplications列表中,并将其视为第一个Application存储到ActivityThread.mInitialApplication中,进而调用Application的onCreate方法。

上述步骤完成后,进入ActivityManagerService启动过程的第三步。

[1]原文是:Instrumentation:Base class for implementing application instrumentation code.When running with instrumentation turned on, this class will be instantiated for you before any of the application code, allowing you to monitor all of the interaction the system has with the application.An Instrumentation implementation is described to the system through an AndroidManifest.xml's<instrumentation>tag.

[2]原文是:ContextImpl:Common implementation of Context API, which provides the base context object for Activity and other application components.

[3]原文是:Context:Interface to global information about an application environment.This is an abstract class whose implementation is provided by the Android system.It allows access to application-specific resources and classes, as well as up-calls for application-level operations such as launching activities, broadcasting and receiving intents, etc.

[4]原文是:Context:Interface to global information about an application environment.This is an abstract class whose implementation is provided by the Android system.It allows access to application-specific resources and classes, as well as up-calls for application-level operations such as launching activities, broadcasting and receiving intents, etc.