首先看源码
Application extends ContextWapper
所以当我们在调用Application的 getApplicationContext时 实际上调用的是 ContextWapper的getApplicationContext 方法如下
from ContextWapper.java
@Override
public Context getApplicationContext() {
return mBase.getApplicationContext();
}
mBase 就是 attachBaseContext 时传入的context 看如下代码
form ContextWapper.java
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
再继续追查
attachBaseContext 是一个 protected 方法 他其实是在Application.java 的attach 中调用
from Application.java
final void attach(Context context) {
attachBaseContext(context);
mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}
查找attach 调用的地方
from Instrumentation.java
public Application newApplication(ClassLoader cl, String className, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
Application app = getFactory(context.getPackageName())
.instantiateApplication(cl, className);
app.attach(context);
return app;
}
newApplication 的调用处
from LoadedApk.java
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
if (mApplication != null) {
return mApplication;
}
......................................
try {
java.lang.ClassLoader cl = getClassLoader();
.....................................
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) {
}
mActivityThread.mAllApplications.add(app);
mApplication = app;
.................................
return app;
}
OK 看上面这个代码
生成app实例 并且调用了 attachBaseContext 之后 最终将app实例指向了 mApplication
现在我们知道了 attachBaseContext 中传入的 context 其实是个 ContextImpl 实例
我们查看ContextImpl 的 getApplicationContext方法
from ContextImpl.java
@Override
public Context getApplicationContext() {
return (mPackageInfo != null) ?
mPackageInfo.getApplication() : mMainThread.getApplication();
}
mPackageInfo 其实就是LoadedApk 往下看
from LoadedApk.java
Application getApplication() {
return mApplication;
}
现在知道了 其实getApplicaitonContext 返回的就是mApplication
根据LoadedApk的makeApplication方法里面可以看到
mApplication 是在attachBaseContext 之后 才被赋值的 ,所以你在attachBaseContext 里面去拿 拿到的当然是NULL了