Application 的 onCreate 和 attachBaseContext
Application 的 onCreate 和 attachBaseContext 是 Application 的两个回调方法,通常我们会在其中做一些初始化操作。
onCreate 和 attachBaseContext 顺序: Application 的 attachBaseContext 在 onCreate 之前执行。
handleBindApplication
App 的 application 创建是在 ActivityThread 的 handleBindApplication 方法完成的。
private void handleBindApplication(AppBindData data) {
....
final InstrumentationInfo ii;
....
if (ii != null) {
//1.创建ContentImpl
final 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.创建Instrumentation
final 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 state
app.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