Andriod中Context的理解
本文主要回答以下几个问题:
- Context是什么?承担哪些责任
- 常用的Context类,以及继承关系
- 一个App中会有多少个ContextImpl实例
一、Context继承关系
Android中Context的继承关系如下:
image
- Activity,Service,Application都是ContextWrapper的子类
- ContextWrapper里面引用着一个ContextImpl实例;
- ContextWrapper里所有的方法都是通过调用ContextImpl进行实现;
二、Context类
public abstract class Context{
}
Context 代表一个上下文信息,是一个抽象类,定义了多个abstract方法,由子类实现具体功能。
如:
1、持有SharePreferences
2、持有DataBaseDir、CahceDir、FileDir 等内部路径
3、持有Resources资源类,进而持有getAssets() 等。
4、持有LoadedApk
5、提供 startActivity()
6、发送 sendBroadcast()
7、支持 startService()
Context持有资源信息,持有loadedApk,具有操作SharePrefrences、操作数据库、启动activity、启动service、发送广播等功能。
对,没错, startActivity()、startService()、startBoradCast()都是Context的行为。
二、ContextImpl 类
ContextImpl是Context的主要实现类,Context所定义众多行为,都是由ContextImpl来完成的。
class ContextImpl extends Context {
final void setOuterContext(Context context) {
mOuterContext = context;
}
@Override
public void startActivity(Intent intent) {
warnIfCallingFromSystemProcess();
startActivity(intent, null);
}
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, false, mUser);
}
@Override
public void sendBroadcast(Intent intent) {
warnIfCallingFromSystemProcess();
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.prepareToLeaveProcess(this);
ActivityManager.getService().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
三、ContextWrapper 是Context的包装类。
ContextWrapper 是Context的子类,内部持有一个ContextImpl对象(mBase)。ContextWrapper中所有功能都是由ContextIml实例来完成的。
public class ContextWrapper extends Context {
Context mBase;
public ContextWrapper(Context base) {
mBase = base;
}
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
@Override
public void startActivity(Intent intent) {
mBase.startActivity(intent);
}
@Override
public ComponentName startService(Intent service) {
return mBase.startService(service);
}
@Override
public void sendBroadcast(Intent intent) {
mBase.sendBroadcast(intent);
}
}
ContextWrapper.attachBaseContext()方法将ContextImpl对象的绑定:
ContextWrapper.java
protected void attachBaseContext(Context base) {
mBase = base;
}
ContextWrapper.mBase指向持有的ContextImpl类,
同时ContextImpl.mOuterContext 指向外部的ContextWrapper类。
ContextImpl.java
final void setOuterContext(Context context) {
mOuterContext = context;
}
四、Application、Activity、Service 都是ContextWrapper的子类,继承了Context的能力。
4.1、Application的创建:
private void handleBindApplication(AppBindData data) {
//这是LoadedApk首次创建的地方
//创建或加载LoadedApk (一个packageName包名对应一个LoadedApk,
首次调用创建LoadedApk,然后缓存在mPackages中,再次调用直接取缓存的loadedApk对象。所以LoadedApk 整个进程只有一个实例。
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
//LoadedApk创建Application对象
app = data.info.makeApplication(data.restrictedBackupMode, null);
//调用Application的onCreate()生命周期
mInstrumentation.callApplicationOnCreate(app);
}
LoadedApk中 首先创建了一个ContextImpl实例,利用Instrumentation创建Application实例,然后将application赋值到contextImpl的OuterContext上。至此完成了ContextImpl->ContextWrapper的绑定。
LoadedApk.java
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
//(1)创建一个ContextImpl实例
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
//(2) 创建一个Application实例
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
//(3)为contextImpl指令outerContext
appContext.setOuterContext(app);
}
我们再看Instrumentation中,创建Application之后,调用了app.attach(context)方法.
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;
}
Application.attach()方法 调用自身的attachBaseContext(),将ContextImpl实例赋值到ContextWrapper.mBase属性上。至此完成了ContextWrapper->ContextImpl的绑定
Application.java
/* package */ final void attach(Context context) {
attachBaseContext(context);
mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}
4.2、Service的创建
private void handleCreateService(CreateServiceData data) {
//获取LoadedApk
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent);
//(1)通过LoadedApk 和ActivityThread 创建一个ContextImpl 实例
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
//(2)为ContextImpl设置OuterContext
context.setOuterContext(service);
//LoadedApk 创建Application对象
Application app = packageInfo.makeApplication(false, mInstrumentation);
//(3) attach()方法 中,将ContextImpl实例传递给Service的mBase属性上。
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
service.onCreate();
mServices.put(data.token, service);
try {
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
"Unable to create service " + data.info.name
+ ": " + e.toString(), e);
}
}
}
- (1)通过LoadedApk 和ActivityThread 创建一个ContextImpl 实例
- (2)为ContextImpl设置OuterContext
- (3) attach()方法 中,将ContextImpl实例传递给Service的mBase属性上。
4.3、Activity 的创建
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent)
//(1)创建ContextImpl
ContextImpl appContext = createBaseContextForActivity(r);
//(2)创建Activity
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
//(3)完成Activity和ContextImpl的双向绑定
appContext.setOuterContext(activity);
activity.attach(appContext, this, getInstrumentation(),...);
}
private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {
ContextImpl appContext = ContextImpl.createActivityContext(
this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);
}
- (1)创建ContextImpl
- (2)利用Instrumentation创建Activity
- (3)完成Activity和ContextImpl的双向绑定
4.4、app中ContextImpl实例的个数:
由上面分析可知:
每创建一个Application、Service 或者Activity 就会创建一个ConetxtImpl实例
Appliation和Service中的ContextImpl实例是相同的(创建方式相同,不是同一个实例),而Activity的ContextImpl不同于Application和Service
Applicaiton和Service ContentImpl的创建方式
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
Activity中ContextImp的创建方式
private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {
ContextImpl appContext = ContextImpl.createActivityContext(
this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);