說明:基於API 26的源碼分析java
Context: 是一個抽象類。bash
ContextImpl: 是Context真正的實現類。app
ContextWrapper: 繼承Context,是一個包裝類,有一個mBase的成員變量,mBase是Context類型,Context抽象方法都是由mBase實現的。子類經過調用attachBaseContext方法替換mBase成員變量。源碼分析
Application, Activity, Service都是繼承ContextWrapper,它們的真正的實現都是ContextImpl實例,ui
經過attachBaseContext方法把ContextImpl實例賦值給mBase。this
因此在activity或者application中經常使用的方法,例如 :spa
上述的經常使用的方法真正實現都是在ContextImplcode
Application的實例從ActivityThread的handleBindApplication(),再到LoadedApk的makeApplication()建立的。orm
cl是ClassLoader, appClass是Application的全類名, 經過ContextImpl.createAppContext建立一個ContextImpl實例,把ContextImpl實例、cl、appClass傳到mInstrumentation.newApplication方法建立Application實例。cdn
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的attach方法:
/* package */ final void attach(Context context) {
attachBaseContext(context);
mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}
複製代碼
先經過classLoader的loadClass(className)獲取application的class,再經過clazz.newInstance()建立Application實例,接着調用app.attach(context)方法完成初始化。 Application的attach方法裏是經過attachBaseContext(context), 把第一步建立的ContextImpl實例賦值給ContextWrapper的mBase成員變量。 到此Application實例建立就完成啦。
Activity建立和Application的建立相似,在ActivityThread的performLaunchActivity方法裏
經過creatBaseContextForActivity方法建立ContextImpl實例,接着經過mInstrumentation.newActivity建立Activity實例,Activity實例經過classloader,加載className,調用clazz的newInstance方法建立。再接着調用activity.attach方法完成初始化。
Activity的attach方法裏是經過attachBaseContext(context), 把第一步建立的ContextImpl實例賦值給ContextWrapper的mBase成員變量。 到此Activity實例建立就完成啦。
Service裏的Context建立和Activity差很少
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = (Service) cl.loadClass(data.info.name).newInstance();
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
Application app = packageInfo.makeApplication(false, mInstrumentation);
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
service.onCreate();
複製代碼
調用ContextImpl的createAppContext()建立ContextImpl,調用setOuterContext()把service存儲在ContextImpl的mOuterContext成員變量中,調用service.attach(),再調用service.onCreate()
public final void attach(
Context context,
ActivityThread thread, String className, IBinder token,
Application application, Object activityManager) {
attachBaseContext(context);
mThread = thread;
mClassName = className;
mToken = token;
mApplication = application;
mActivityManager = (IActivityManager)activityManager;
mStartCompatibility = getApplicationInfo().targetSdkVersion
< Build.VERSION_CODES.ECLAIR;
}
複製代碼
經過attachBaseContext(context), 把第一步建立的ContextImpl實例賦值給ContextWrapper的mBase成員變量。
ContextWrapper繼承Context。Application, Activity, Service都是繼承ContextWrapper,它們的真正的實現都是ContextImpl實例,經過attachBaseContext方法把ContextImpl實例賦值給mBase。Context裏抽象方法真正實現都是在ContextImpl裏。
還有一個共同點: