Application 的 onCreate 和 attachBaseContext
Application 的 onCreate 和 attachBaseContext 是 Application 的两个回调方法,通常我们会在其中做一些初始化操作。
onCreate 和 attachBaseContext 顺序: Application 的 attachBaseContext 在 onCreate 之前执行。
App 的 application 创建是在 ActivityThread 的 handleBindApplication 方法完成的。
private void handleBindApplication(AppBindData data) {....final InstrumentationInfo ii;....if (ii != null) {//1.创建ContentImplfinal ContextImpl instrContext = ContextImpl.createAppContext(this, pi);try {final ClassLoader cl = instrContext.getClassLoader();mInstrumentation = (Instrumentation)cl.loadClass(data.instrumentationName.getClassName()).newInstance();} catch (Exception e) {throw new RuntimeException("Unable to instantiate instrumentation "+ data.instrumentationName + ": " + e.toString(), e);}//2.创建Instrumentationfinal ComponentName component = new ComponentName(ii.packageName, ii.name);mInstrumentation.init(this, instrContext, appContext, component,data.instrumentationWatcher, data.instrumentationUiAutomationConnection);....//3.创建Application对象Application app;app = data.info.makeApplication(data.restrictedBackupMode, null);// Propagate autofill compat stateapp.setAutofillCompatibilityEnabled(data.autofillCompatibilityEnabled);mInitialApplication = app;...//4.启动当前进程中的ContentProvider和调用其onCreate方法if (!data.restrictedBackupMode) {if (!ArrayUtils.isEmpty(data.providers)) {installContentProviders(app, data.providers);// For process that contains content providers, we want to// ensure that the JIT is enabled "at some point".mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);}}//5.调用Application的onCreate方法try {mInstrumentation.callApplicationOnCreate(app);} catch (Exception e) {if (!mInstrumentation.onException(app, e)) {throw new RuntimeException("Unable to create application " + app.getClass().getName()+ ": " + e.toString(), e);}}}}
可以看到初始化顺序: 1.创建ContentImpl -> 2.创建Instrumentation -> 3.创建Application对象 并调用 attachBaseContext方法 -> 4.启动当前进程中的ContentProvider和调用其onCreate方法 -> 5.调用Application的onCreate方法
Application 的 attachBaseContext 在 onCreate 之前执行。attachBaseContext 中拿到了创建的 ContextImpl,但是此时 Application 没有创建完成,比如 mLoadedApk 的赋值还没有执行。此时如果在 attachBaseContext 中调用 this.getApplicationContext,也会返回空,因为 application 还没有创建完成。等到回调了 onCreate 时,Application 才算真正构造完毕。
如果项目中的初始化都是同步初始化的话,并且使用到了多个ContentProvider,App Startup 还是不错的,毕竟统一到了一个ContentProvider中,同时支持了简单的顺序依赖。
但是如果在追求App性能与启动速度的场景中,多个SDK同时利用各自定义的ContentProvider实现“自启动”, 在各种有先后顺序与依赖的SDK初始化下做优化,那么 App Startup 就不是很好用了。也正式这个原因,目前不建议将 App Startup 用于生产环境中。
目前的推荐方案还是之前我们都使用过的:同步+异步初始化,并通过有向无环图拓扑排序的方式; Anchors