ContextImpl关键成员和函数
/**
* Common implementation of Context API, which provides the base
* context object for Activity and other application components.
*/
classContextImplextendsContext {
privatefinalstaticString TAG ="ContextImpl";
privatefinalstaticbooleanDEBUG =false;
privatestaticfinalHashMap sSharedPrefs =
newHashMap();
/*package*/LoadedApk mPackageInfo;// 关键数据成员
privateString mBasePackageName;
privateResources mResources;
/*package*/ActivityThread mMainThread;// 主线程
@Override
publicAssetManager getAssets() {
returngetResources().getAssets();
}
@Override
publicLooper getMainLooper() {
returnmMainThread.getLooper();
}
@Override
publicObject getSystemService(String name) {
ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);
returnfetcher ==null?null: fetcher.getService(this);
}
@Override
publicvoidstartActivity(Intent intent, Bundle options) {
warnIfCallingFromSystemProcess();
if((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) ==0) {
thrownewAndroidRuntimeException(
"Calling startActivity() from outside of an Activity "
+ " context requires the FLAG_ACTIVITY_NEW_TASK flag."
+ " Is this really what you want?");
}
mMainThread.getInstrumentation().execStartActivity(
getOuterContext(), mMainThread.getApplicationThread(), null,
(Activity)null, intent, -1, options);
}
}
ContextWrapper
它只是对Context类的一种封装,它的构造函数包含了一个真正的Context引用,即ContextImpl对象。
/**
* Proxying implementation of Context that simply delegates all of its calls to
* another Context.  Can be subclassed to modify behavior without changing
* the original Context.
*/
publicclassContextWrapperextendsContext {
Context mBase; //该属性指向一个ContextIml实例
publicContextWrapper(Context base) {
mBase = base;
}
/**
* Set the base context for this ContextWrapper.  All calls will then be
* delegated to the base context.  Throws
* IllegalStateException if a base context has already been set.
*
* @param base The new base context for this wrapper.
* 创建Application、Service、Activity,会调用该方法给mBase属性赋值
*/
protectedvoidattachBaseContext(Context base) {
if(mBase !=null) {
thrownewIllegalStateException("Base context already set");
}
mBase = base;
}
@Override
publicLooper getMainLooper() {
returnmBase.getMainLooper();
}
@Override
publicObject getSystemService(String name) {
returnmBase.getSystemService(name);
}
@Override
publicvoidstartActivity(Intent intent) {
mBase.startActivity(intent);
}
}
ContextThemeWrapper
该类内部包含了主题(Theme)相关的接口,即android:theme属性指定的。只有Activity需要主题,Service不需要主题,所以Service直接继承于ContextWrapper类。
/**
* A ContextWrapper that allows you to modify the theme from what is in the
* wrapped context.
*/
publicclassContextThemeWrapperextendsContextWrapper {
privateContext mBase;
privateintmThemeResource;
privateResources.Theme mTheme;
privateLayoutInflater mInflater;
privateConfiguration mOverrideConfiguration;
privateResources mResources;
publicContextThemeWrapper() {
super(null);
}
publicContextThemeWrapper(Context base,intthemeres) {
super(base);
mBase = base;
mThemeResource = themeres;
}
@OverrideprotectedvoidattachBaseContext(Context newBase) {
super.attachBaseContext(newBase);
mBase = newBase;
}
@OverridepublicvoidsetTheme(intresid) {
mThemeResource = resid;
initializeTheme();
}
@OverridepublicResources.Theme getTheme() {
if(mTheme !=null) {
returnmTheme;
}
mThemeResource = Resources.selectDefaultTheme(mThemeResource,
getApplicationInfo().targetSdkVersion);
initializeTheme();
returnmTheme;
}
}
何时创建Context
应用程序在以下几种情况下创建Context实例:
1) 创建Application 对象时, 而且整个App共一个Application对象
2) 创建Service对象时
3) 创建Activity对象时
因此应用程序App共有的Context数目公式为:
总Context实例个数 = Service个数 + Activity个数 + 1(Application对应的Context实例)
ActivityThread消息处理函数与本节相关的内容如下:
publicvoidhandleMessage(Message msg) {
if(DEBUG_MESSAGES) Slog.v(TAG,">>> handling: "+ codeToString(msg.what));
switch(msg.what) {
caseLAUNCH_ACTIVITY: {// 创建Activity对象
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
caseBIND_APPLICATION:// 创建Application对象
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
caseCREATE_SERVICE:// 创建Service对象
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate");
handleCreateService((CreateServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
caseBIND_SERVICE:// Bind Service对象
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
handleBindService((BindServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
}
}
创建Application对象时创建Context实例
每个应用程序在第一次启动时,都会首先创建一个Application对象。从startActivity流程可知,创建Application的时机在handleBindApplication()方法中,该函数位于 ActivityThread.java类中 ,相关代码如下:
// ActivityThread.java
privatevoidhandleBindApplication(AppBindData data) {
try{
// If the app is being launched for full backup or restore, bring it up in
// a restricted environment with the base application class.
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
...
} finally{
StrictMode.setThreadPolicy(savedPolicy);
}
}
// LoadedApk.java
publicApplication makeApplication(booleanforceDefaultAppClass,
Instrumentation instrumentation) {
if(mApplication !=null) {
returnmApplication;
}
Application app = null;
String appClass = mApplicationInfo.className;
if(forceDefaultAppClass || (appClass ==null)) {
appClass = "android.app.Application";
}
try{
java.lang.ClassLoader cl = getClassLoader();
ContextImpl appContext = newContextImpl();// 创建ContextImpl实例
appContext.init(this,null, mActivityThread);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app); // 将Application实例传递给Context实例
} catch(Exception e) {
...
}
mActivityThread.mAllApplications.add(app);
mApplication = app;
returnapp;
}
创建Activity对象时创建Context实例
通过startActivity()或startActivityForResult()请求启动一个Activity时,如果系统检测需要新建一个Activity对象时,就会回调handleLaunchActivity()方法,该方法继而调用performLaunchActivity()方法,去创建一个Activity实例,并且回调onCreate(),onStart()方法等,函数都位于 ActivityThread.java类 ,相关代码如下:
privatevoidhandleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
Activity a = performLaunchActivity(r, customIntent); // 到下一步
if(a !=null) {
r.createdConfig = newConfiguration(mConfiguration);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed);
...
}
...
}
privateActivity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
Activity activity = null;
try{
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
if(r.state !=null) {
r.state.setClassLoader(cl);
}
} catch(Exception e) {
...
}
try{
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if(activity !=null) {
Context appContext = createBaseContextForActivity(r, activity); // 创建Context
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = newConfiguration(mCompatConfiguration);
if(DEBUG_CONFIGURATION) Slog.v(TAG,"Launching activity "
+ r.activityInfo.name + " with config "+ config);
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config);
if(customIntent !=null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
activity.mStartedActivity = false;
inttheme = r.activityInfo.getThemeResource();
if(theme !=0) {
activity.setTheme(theme);
}
mActivities.put(r.token, r);
} catch(SuperNotCalledException e) {
...
} catch(Exception e) {
...
}
returnactivity;
}
privateContext createBaseContextForActivity(ActivityClientRecord r,
finalActivity activity) {
ContextImpl appContext = newContextImpl();// 创建ContextImpl实例
appContext.init(r.packageInfo, r.token, this);
appContext.setOuterContext(activity);
// For debugging purposes, if the activity's package name contains the value of
// the "debug.use-second-display" system property as a substring, then show
// its content on a secondary display if there is one.
Context baseContext = appContext;
String pkgName = SystemProperties.get("debug.second-display.pkg");
if(pkgName !=null&& !pkgName.isEmpty()
&& r.packageInfo.mPackageName.contains(pkgName)) {
DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
for(intdisplayId : dm.getDisplayIds()) {
if(displayId != Display.DEFAULT_DISPLAY) {
Display display = dm.getRealDisplay(displayId);
baseContext = appContext.createDisplayContext(display);
break;
}
}
}
returnbaseContext;
}
创建Service对象时创建Context实例
通过startService或者bindService时,如果系统检测到需要新创建一个Service实例,就会回调handleCreateService()方法,完成相关数据操作。handleCreateService()函数位于 ActivityThread.java类,如下:
privatevoidhandleCreateService(CreateServiceData data) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try{
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = (Service) cl.loadClass(data.info.name).newInstance();
} catch(Exception e) {
if(!mInstrumentation.onException(service, e)) {
thrownewRuntimeException(
"Unable to instantiate service "+ data.info.name
+ ": "+ e.toString(), e);
}
}
try{
if(localLOGV) Slog.v(TAG,"Creating service "+ data.info.name);
ContextImpl context = newContextImpl();// 创建ContextImpl实例
context.init(packageInfo, null,this);
Application app = packageInfo.makeApplication(false, mInstrumentation);
context.setOuterContext(service);
service.attach(context, this, data.info.name, data.token, app,
ActivityManagerNative.getDefault());
service.onCreate();
mServices.put(data.token, service);
try{
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, 0,0,0);
} catch(RemoteException e) {
// nothing to do.
}
} catch(Exception e) {
if(!mInstrumentation.onException(service, e)) {
thrownewRuntimeException(
"Unable to create service "+ data.info.name
+ ": "+ e.toString(), e);
}
}
}

小结

通过对ContextImp的分析可知,其方法的大多数操作都是直接调用其属性mPackageInfo(该属性类型为PackageInfo)的相关方法而来。这说明ContextImp是一种轻量级类,而PackageInfo才是真正重量级的类。而一个App里的所有ContextImpl实例,都对应同一个packageInfo对象。