基本类结构:
public class ContextWrapper extends Context {
Context mBase;
public ContextWrapper(Context base) {
mBase = base;
}
//为ContextWrapper设置它的ContextImpl
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
public Context getBaseContext() {
return mBase;
}
}
这里的base就是一个ContextImpl类,base负责Context的实际的处理逻辑
Activity中的contextImpl的创建过程:
启动Activity时会调用ActivityThread的以下方法:
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
Activity activity = null;
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (activity != null) {
//创建与Activity关联的ContextImpl
Context appContext = createBaseContextForActivity(r, activity); //1
//调用attach把activity关联到新创建的contextImpl
//没有关联contextImpl的Context很多方法是不可用的,因为contextImpl是实现方法的实体
activity.attach(appContext, this, getInstrumentation(), r.token, app, r.intent, ...); //2
}
return activity;
}
注释1处:
private Context createBaseContextForActivity(ActivityClientRecord r, final Activity activity) {
ContextImpl appContext = ContextImpl.createActivityContext(this, r.packageInfo, r.token);
appContext.setOuterContext(activity);
Context baseContext = appContext;
return baseContext;
}
在注释2处activity.attach()方法中调用了attachBaseContext(),将新创建的ContextImpl赋值给mBase
Application创建ContextImpl的过程:
//冷启动时当前应用还没有Application,创建Application
public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) {
if (mApplication != null) {
return mApplication;
}
java.lang.ClassLoader cl = getClassLoader();
//和Activity一样都调用了ContextImpl.createActivityContext
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext); //1
appContext.setOuterContext(app);
mApplication = app;
return app;
}
注释1处:
static public Application newApplication(Class<?> clazz, Context context){
Application app = (Application)clazz.newInstance();
app.attach(context); //里面调用了attachBaseContext(context)去关联contextImpl
return app;
}
每个ContextWrapper都有不同的ContextImpl,如何保证不同ContextImpl访问的资源是同样的?
看ContextImpl的源码:
class ContextImpl extends Context {
private static final HashMap<String, ServiceFetcher> SYSTEM_SERVICE_MAP =
new HashMap<String, ServiceFetcher>();
private final ResourcesManager mResourcesManager;
private final Resources mResources;
private ContextImpl(ActivityThread mainThread,LoadedApk packageInfo,...){
mResourcesManager = ResourcesManager.getInstance(); //单例
Resources resources = packageInfo.getResources(mainThread); //packageInfo是同一个
mResources = mResourcesManager.getTopLevelResources(....);
}
public AssetManager getAssets() {
return getResources().getAssets();
}
public Resources getResources() {
return mResources;
}
static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
return new ContextImpl(null, mainThread, ...)
}
private static void registerService(String serviceName, ServiceFetcher fetcher) {
SYSTEM_SERVICE_MAP.put(serviceName, fetcher);
}
public Object getSystemService(String name) {
ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);
return fetcher == null ? null : fetcher.getService(this);
}
}
getApplication和getApplicationContext的区别:
getApplication方法只有Activity和Service才有,它返回了一个Application对象;
getApplicationContext()是Context的方法,它返回了一个Context对象
二者返回的对象是同一个Application