android createSystemContext()创建第一个上下文对象

在上一篇博文中分析了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;
    }

此处两者的具体区别下次再补充,该下班了。

珍爱生命,远离加班!
总结:以上就是android设备创建的第一个上下文对象的过程。
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值