一、Activity、Application 和 Service
三者经常和 Context 打交道,它们都和 Context 有关联。
装饰者模式,都继承 ContextWrapper 类,该类提供 attachBaseContext() 方法赋值内部被装饰者具体对象,基类 Context,真实类 ContextImpl。
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;//ContextImpl对象。
}
在 Activity 类的 attach() 方法,ContextImpl 类提供静态方法创建实例。
static ContextImpl createActivityContext(ActivityThread mainThread,
LoadedApk packageInfo, int displayId, Configuration overrideConfiguration) {
if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
return new ContextImpl(null, mainThread, packageInfo, null, null, false,
null, overrideConfiguration, displayId);
}
在 Service 类的 attach() 方法,创建 ContextImpl 实例的静态方法与前者不同。
static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
return new ContextImpl(null, mainThread,
packageInfo, null, null, false, null, null, Display.INVALID_DISPLAY);
}
创建 Application 内部 ContextImpl 实例的方法和 Service 一样,Application 的attach()方法,设置内部 Context。
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
ContextImpl类的setOuterContext()方法,设置外部引用它的Context。
二、ContentProvider和BroadcastReceiver
ContentProvider不继承Context,构造方法创建对象时,入参初始化内部Context。
public ContentProvider(
Context context,
String readPermission,
String writePermission,
PathPermission[] pathPermissions) {
mContext = context;
mReadPermission = readPermission;
mWritePermission = writePermission;
mPathPermissions = pathPermissions;
}
BroadcastReceiver不继承Context,内部无Context对象,在onReceive()方法时传入,该方法可以使用Context功能。
public abstract void onReceive(Context context, Intent intent);
三、常用方法
1,getApplicationContext()方法
在Activity,Service和Application,该方法用于获取Context。
@Override
public Context getApplicationContext() {
return mBase.getApplicationContext();
}
父类ContextWrapper提供方法,真实类ContextImpl的实现方法(Context的抽象方法)。
@Override
public Context getApplicationContext() {
return (mPackageInfo != null) ?
mPackageInfo.getApplication() : mMainThread.getApplication();
}
从LoadedApk类或从ActivityThread类获取,LoadedApk在makeApplication()方法赋值,ActivityThread在handleBindApplication()方法初始化,也是通过LoadedApk类的makeApplication()方法创建。
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
因此,getApplicationContext()方法,本质是从ContextImpl对象中获取全局Application。
2,getApplication()方法
在Activity和Service,返回内部Application对象,attach()方法时初始化,全局对象。
四、视图的Context
除组件外,视图也和Context关联,创建时,构造方法Context入参,在Activity组件中,通过代码new一个View对象,传入的Context即this,代表Activity。
public View(Context context) {
mContext = context;
...
}
View类的getContext()方法,返回内部Context,在视图中需要使用Context的一些方法,是Activity的实现方法或ContextImpl的实现方法。
五、总结
1,Activity、Service和Application的基类都是Context类,内部ContextImpl类是真正实现类。
2,ContextImpl对象的构建方法,Activity类和另外二者不同。
3,开发常用方法,getApplicationContext()方法和getApplication()方法区别,前者是Context抽象方法,在ContextImpl具体中类实现,后者是Activity和Service的方法,相同点是都返回全局Application对象。
任重而道远