在上一篇博文中分析了zygote进程到SystemServer进程的启动过程,在SystemServer的run()方法中将会调用createSystemContext() 方法初始化系统上下文对象,本篇将记录该方法创建上下文对象的过程。
android zygote进程启动到SystemServer进程启动过程
直接上代码
private void createSystemContext() {
ActivityThread activityThread = ActivityThread.systemMain(); //第一处,创建ActivityThread 实例
mSystemContext = activityThread.getSystemContext(); //第二处,赋值系统上下文
mSystemContext.setTheme(DEFAULT_SYSTEM_THEME); //第三处,设置系统上下文主题
final Context systemUiContext = activityThread.getSystemUiContext(); //第四处,赋值系统UI上下文
systemUiContext.setTheme(DEFAULT_SYSTEM_THEME); //第五处,设置系统UI上下文主题
}
这里我分为五处来看源码。
1、创建ActivityThread 实例
ActivityThread是什么呢?官方解释如下:点击查看ActivityThread.java源码
* This manages the execution of the main thread in an
* application process, scheduling and executing activities,
* broadcasts, and other operations on it as the activity
* manager requests.
大概的意思就是说:在应用程序里面管理和执行主线程,调度和执行Activity,广播以及在Activity上的其他业务操作。
接着,我们来看第一步:
public static ActivityThread systemMain() {
//低内存设备上的系统进程不能使用硬件加速绘图,因为这会给进程增加太多的开销。
//用于确定进程是否在高端设备上运行,是则应该可以使用硬件绘图加速 (这会消耗更多的内存)。
if (!ActivityManager.isHighEndGfx()) {
ThreadedRenderer.disable(true);
} else {
ThreadedRenderer.enableForegroundTrimming();
}
ActivityThread thread = new ActivityThread(); //直接调用无参构造方法创建实例
thread.attach(true, 0);
return thread;
}
ActivityThread() {
mResourcesManager = ResourcesManager.getInstance();
}
在无参构造方法中,获取到一个ResourcesManager实例,来看看ResourcesManager的这个单例方法:
private static ResourcesManager sResourcesManager;
public static ResourcesManager getInstance() {
synchronized (ResourcesManager.class) {
if (sResourcesManager == null) {
sResourcesManager = new ResourcesManager();
}
return sResourcesManager;
}
}
所以在调用ActivityThread的无参构造方法创建实例的时候,只是创建了一个ResourcesManager实例对象并赋值给自己的成员变量mResourcesManager,接下来重点看看ActivityThread的attach()方法。
private void attach(boolean system, long startSeq) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
//前面调用thread.attach(true, 0),所以,system为true,直接省略这部分
//......
} else {
//......
try {
mInstrumentation = new Instrumentation();
mInstrumentation.basicInit(this); //这个方法我竟然找不到,不知道什么原因,不过看样子应该是绑定当前ActivityThread的方法
ContextImpl context = ContextImpl.createAppContext(this, getSystemContext().mPackageInfo);
mInitialApplication = context.mPackageInfo.makeApplication(true, null);
mInitialApplication.onCreate(); //此处就是我们熟悉的Application的onCreate()方法
} catch (Exception e) {
throw new RuntimeException("Unable to instantiate Application():" + e.toString(), e);
}
}
//......
}
Application mInitialApplication;
- 首先是创建并实例化了一个Instrumentation对象
- 然后先调用了ContextImpl的静态方法createAppContext() 创建了一个实例
- 紧接着调用上面的ContextImpl实例context来创建Application对象,此处的Application就是我们程序入口的那个Application,我们看看怎么创建的
首先context.mPackageInfo是一个LoadedApk对象,我们看看它的makeApplication方法:
public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) {
if (mApplication != null) { //若是已经创建,则直接返回
return mApplication;
}
//......
Application app = null;
String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) { //此处的forceDefaultAppClass传过来的时候为ture
appClass = "android.app.Application"; //所以,此处的Application是默认基类
//如果我们继承了Application就不会走上面这步了
}
try {
//......
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this); //简单赋值的构造方法
app = mActivityThread.mInstrumentation.newApplication( cl, appClass, appContext);
//......
} catch (Exception e) {
//......
}
//......
mApplication = app;
if (instrumentation != null) {
try {
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
//......
}
}
//......
return app;
}
上面可以看到,最终调用了Instrumentation的newApplication创建mApplication对象的:
public Application newApplication(ClassLoader cl, String className, Context context)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return newApplication(cl.loadClass(className), context);
}
static public Application newApplication(Class<?> clazz, Context context)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
Application app = (Application)clazz.newInstance();
app.attach(context);
return app;
}
最终发现,是通过反射创建了Application实例,并调用了Application自身的attach()方法,后面会跟着调用onCreate()方法。以上就是Application的创建过程。
小结:通过重重的调用,无非创建了ActivityThread实例,绑定了Instrumentation实例,然后创建了ResourcesManager,最后通过反射创建了Application实例对象。
2、赋值上下文
我们可以发现,第二步到第五步,两者很相似:
mSystemContext = activityThread.getSystemContext();
systemUiContext = activityThread.getSystemUiContext();
再看看activityThread的两个静态方法
public ContextImpl getSystemContext() {
synchronized (this) {
if (mSystemContext == null) {
mSystemContext = ContextImpl.createSystemContext(this);
}
return mSystemContext;
}
}
public ContextImpl getSystemUiContext() {
synchronized (this) {
if (mSystemUiContext == null) {
mSystemUiContext = ContextImpl.createSystemUiContext(getSystemContext());
}
return mSystemUiContext;
}
}
渐渐的可以发现,调用ContextImpl 的两个静态方法时,前者传入的是activityThread对象,后者传入的是前者的对象实例。
static ContextImpl createSystemContext(ActivityThread mainThread) {
LoadedApk packageInfo = new LoadedApk(mainThread);
ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
null);
context.setResources(packageInfo.getResources());
context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
context.mResourcesManager.getDisplayMetrics());
return context;
}
//用于UI的系统上下文。这个上下文具有可以主题化的资源。确保创建的系统UI上下文与系统上下文共享相同的LoadedApk。
static ContextImpl createSystemUiContext(ContextImpl systemContext) {
final LoadedApk packageInfo = systemContext.mPackageInfo;
ContextImpl context = new ContextImpl(null, systemContext.mMainThread, packageInfo, null,
null, null, 0, null);
context.setResources(createResources(null, packageInfo, null, Display.DEFAULT_DISPLAY, null,
packageInfo.getCompatibilityInfo()));
return context;
}
此处两者的具体区别下次再补充,该下班了。