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對象。
【責任編輯:chenqingxiang TEL:(010)68476606】