? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??? ? ? ? ? ? ? ? Context
?? Context,翻譯是上下文環(huán)境,在android應(yīng)用開發(fā)中的地位舉足輕重,甚至源碼也有一句話:everything needs a context(看到過,但是忘了在哪里了)。

從這個(gè)類圖中我們看到,Context是一個(gè)抽象類,一邊是Context的具體實(shí)現(xiàn)ContextImpl,一邊則是組件的封裝類ContextWrapper,便于二者各司其職,我理解是接口和實(shí)現(xiàn)分開,這樣比較符合開閉原則吧。
? 既然要搞清楚Context是干嘛的,得先看Context的實(shí)例什么時(shí)候創(chuàng)建的。這里有兩個(gè)我們經(jīng)常接觸的組件,Activity和Service,以及用的較少的Application,它們的關(guān)系如下:
? ? 1.Application:保存應(yīng)用的全局信息的類,它的實(shí)例在應(yīng)用創(chuàng)建的時(shí)候被創(chuàng)建,生命周期最長(zhǎng),應(yīng)用銷毀了才會(huì)被銷毀。
? ? 2.Activity:創(chuàng)建一個(gè)Activity便對(duì)應(yīng)一個(gè)Context的實(shí)例,生命周期隨著Activity的周期變化。
? ? 3.Service:創(chuàng)建一個(gè)Service便對(duì)應(yīng)一個(gè)Context的實(shí)例,生命周期隨著Service的周期變化。
下面逐一看看它們是什么時(shí)候?qū)嵗鼵ontext類的,我們需要知道,一個(gè)ContextWrapper類對(duì)應(yīng)一個(gè)ContextImpl類的實(shí)例,因?yàn)榫唧w實(shí)現(xiàn)的地方還是在ContextImpl中,ContextWrapper中的mBase變量指向ContextImpl變量的實(shí)例。
(1) Application的Context創(chuàng)建:
如圖:

? 跳過Process創(chuàng)建過程,在我們的應(yīng)用被zygote進(jìn)程孵化出來后,被反射調(diào)用main函數(shù),這里會(huì)創(chuàng)建ActivityThread類的實(shí)例,該類并不是一個(gè)線程類的子類,但是它的main函數(shù)跑在新創(chuàng)建的進(jìn)程的主線程。 創(chuàng)建后,調(diào)用attach方法,與AMS綁定:
```java
private void attach(boolean system) {
? ? if (!system) {
? ? ? ? final IActivityManager mgr = ActivityManager.getService();
? ? ? ? try {
? ? ? ? ? ? mgr.attachApplication(mAppThread);? // final ApplicationThread mAppThread = new ApplicationThread();
? ? ? ? } catch (RemoteException ex) {
? ? ? ? ? ? throw ex.rethrowFromSystemServer();
? ? ? ? }
? ? }
}
```
這里傳入的mAppThread變量為ApplicationThread類,它為ActivityThread的內(nèi)部類,作用就是作為應(yīng)用端的binder服務(wù)端,負(fù)責(zé)接收AMS的調(diào)度,這里我們傳入這個(gè)服務(wù)端的句柄,讓AMS持有,從而AMS可以通過這個(gè)句柄來操控應(yīng)用的行為。我們向AMS請(qǐng)求,則是通過AMS的句柄。接下來就到了AMS的邏輯:
@Override
public final void attachApplication(IApplicationThread thread) {
?? synchronized (this) {
? ? ?? int callingPid = Binder.getCallingPid();
? ? ?? final long origId = Binder.clearCallingIdentity();
? ? ?? attachApplicationLocked(thread, callingPid);
? ? ?? Binder.restoreCallingIdentity(origId);
?? }
}
-----------------------------------------------------------------------
?? private final boolean attachApplicationLocked(IApplicationThread thread,
? ? ? ? ?? int pid) {
? ? ? ? ?? ProcessRecord app;? //app進(jìn)程的各種信息
? ? ? ? ?? app.makeActive(thread, mProcessStats);? //將IApplicationThread對(duì)象保存到ProcessRecord中
? ? ? ? ?? if (app.instr != null) {
? ? ? ? ? ? ?? thread.bindApplication(processName, appInfo, providers,? //通知客戶端創(chuàng)建Application對(duì)象
? ? ? ? ? ? ? ? ? ? ?? app.instr.mClass,
? ? ? ? ? ? ? ? ? ? ?? profilerInfo, app.instr.mArguments,
? ? ? ? ? ? ? ? ? ? ?? app.instr.mWatcher,
? ? ? ? ? ? ? ? ? ? ?? app.instr.mUiAutomationConnection, testMode,
? ? ? ? ? ? ? ? ? ? ?? mBinderTransactionTrackingEnabled, enableTrackAllocation,
? ? ? ? ? ? ? ? ? ? ?? isRestrictedBackupMode || !normalMode, app.persistent,
? ? ? ? ? ? ? ? ? ? ?? new Configuration(getGlobalConfiguration()), app.compat,
? ? ? ? ? ? ? ? ? ? ?? getCommonServicesLocked(app.isolated),
? ? ? ? ? ? ? ? ? ? ?? mCoreSettingsObserver.getCoreSettingsLocked(),
? ? ? ? ? ? ? ? ? ? ?? buildSerial);
? ? ? ? ?? } else {
? ? ? ? ? ? ?? thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
? ? ? ? ? ? ? ? ? ? ?? null, null, null, testMode,
? ? ? ? ? ? ? ? ? ? ?? mBinderTransactionTrackingEnabled, enableTrackAllocation,
? ? ? ? ? ? ? ? ? ? ?? isRestrictedBackupMode || !normalMode, app.persistent,
? ? ? ? ? ? ? ? ? ? ?? new Configuration(getGlobalConfiguration()), app.compat,
? ? ? ? ? ? ? ? ? ? ?? getCommonServicesLocked(app.isolated),
? ? ? ? ? ? ? ? ? ? ?? mCoreSettingsObserver.getCoreSettingsLocked(),
? ? ? ? ? ? ? ? ? ? ?? buildSerial);
? ? ? ? ?? }
? ? ?? return true;
?? }
? ? 在ApplicationThread的實(shí)現(xiàn)端中,就是把跨進(jìn)程傳遞過來的各種數(shù)據(jù)再用一個(gè)AppBindData類保存下來,然后調(diào)用Handler對(duì)象H發(fā)送消息BIND_APPLICATION,最后在app線程中處理此邏輯,讓AMS線程可以不必同步阻塞。接下來就到了handleBindApplication:
private void handleBindApplication(AppBindData data) {
?? mBoundApplication = data;
?? final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
?? updateLocaleListFromAppContext(appContext,
? ? ? ? ?? mResourcesManager.getConfiguration().getLocales());
?? if (ii != null) {
? ? ?? final ApplicationInfo instrApp = new ApplicationInfo();
? ? ?? ii.copyTo(instrApp);
? ? ?? instrApp.initForUser(UserHandle.myUserId());
? ? ?? final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
? ? ? ? ? ? ?? appContext.getClassLoader(), false, true, false);
? ? ?? final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
? ? ?? try {
? ? ? ? ?? final ClassLoader cl = instrContext.getClassLoader();
? ? ? ? ?? mInstrumentation = (Instrumentation) ? //創(chuàng)建Instrumentation類對(duì)象
? ? ? ? ? ? ?? cl.loadClass(data.instrumentationName.getClassName()).newInstance();
? ? ?? } catch (Exception e) {
? ? ? ? ?? throw new RuntimeException(
? ? ? ? ? ? ?? "Unable to instantiate instrumentation "
? ? ? ? ? ? ?? + data.instrumentationName + ": " + e.toString(), e);
? ? ?? }
? ? ?? final ComponentName component = new ComponentName(ii.packageName, ii.name);
? ? ?? mInstrumentation.init(this, instrContext, appContext, component,
? ? ? ? ? ? ?? data.instrumentationWatcher, data.instrumentationUiAutomationConnection);? //初始化Instrumentation
?? 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);? //創(chuàng)建Application類對(duì)象
? ? ?? mInitialApplication = app;
? ? ?? }
}
? ? Instrumentation類是用于管理Acitivty的工具類。這又有一個(gè)比較重要的對(duì)象出現(xiàn),LoadedApk,它里面保存了類加載器ClassLoader,data.info的對(duì)象便是它,makeApplication函數(shù)中的邏輯:
public Application makeApplication(boolean forceDefaultAppClass,
? ? ?? Instrumentation instrumentation) {
?? if (mApplication != null) {? //保證唯一性,不會(huì)重復(fù)創(chuàng)建Application對(duì)象,所以我們可以認(rèn)為Application對(duì)象是單例的
? ? ?? return mApplication;
?? }
?? Application app = null;
?? String appClass = mApplicationInfo.className;
?? try {
? ? ?? java.lang.ClassLoader cl = getClassLoader();? //獲取類加載器實(shí)例
? ? ?? ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this); //創(chuàng)建ContextImpl實(shí)例
? ? ?? app = mActivityThread.mInstrumentation.newApplication( ? //實(shí)際創(chuàng)建Application對(duì)象的地方
? ? ? ? ? ? ?? cl, appClass, appContext); ?
? ? ?? appContext.setOuterContext(app);
?? } catch (Exception e) {
? ? ?? if (!mActivityThread.mInstrumentation.onException(app, e)) {
? ? ? ? ?? Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
? ? ? ? ?? throw new RuntimeException(
? ? ? ? ? ? ?? "Unable to instantiate application " + appClass
? ? ? ? ? ? ?? + ": " + e.toString(), e);
? ? ?? }
?? }
?? mActivityThread.mAllApplications.add(app);
?? mApplication = app;
?? if (instrumentation != null) {
? ? ?? try {
? ? ? ? ?? instrumentation.callApplicationOnCreate(app); ? //Application的onCreate()被調(diào)用
? ? ?? } catch (Exception e) {
? ? ? ? ?? if (!instrumentation.onException(app, e)) {
? ? ? ? ? ? ?? Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
? ? ? ? ? ? ?? throw new RuntimeException(
? ? ? ? ? ? ? ? ?? "Unable to create application " + app.getClass().getName()
? ? ? ? ? ? ? ? ?? + ": " + e.toString(), e);
? ? ? ? ?? }
? ? ?? }
?? }
?? return app;
}
? 這里我們看到了ContextImpl的創(chuàng)建時(shí)機(jī),就是在Application實(shí)例創(chuàng)建的時(shí)候:
?? 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的創(chuàng)建,并且調(diào)用attach方法把Application的mBase對(duì)象賦值給創(chuàng)建的ContextImpl,至此Application的創(chuàng)建就完成了,getApplicationContext() 返回的便是此處我們創(chuàng)建的Application類的對(duì)象。
? 這里為什么要去LoadedApk類中利用類加載器,把對(duì)象創(chuàng)建出來呢?因?yàn)槲覀兊腁pplication類是可以自己拓展的,創(chuàng)建的時(shí)候是不確定應(yīng)用自己是否復(fù)寫了Application對(duì)象,利用類加載器就可以動(dòng)態(tài)決定創(chuàng)建什么類的對(duì)象了,我們只需要從PMS中獲取到application的具體類名即可,這個(gè)類名是寫在Mainfest文件中的,后面Activity也是利用這種機(jī)制去創(chuàng)建對(duì)象。
(2)Actvity的啟動(dòng)過程,網(wǎng)上非常多文章分析了,我也就不再重復(fù)羅列出來了,大概的過程就是startActivity()被調(diào)用,然后檢查目標(biāo)Acitivity的進(jìn)程是否創(chuàng)建,沒創(chuàng)建就先向Zygote進(jìn)程請(qǐng)求fork應(yīng)用進(jìn)程,然后一系列初始化過程后,最后在AMS模塊中的ActivityStackSupervisor中realStartActivityLocked()調(diào)用IApplicationThread代理類,調(diào)用到scheduleLaunchActivity(),然后在應(yīng)用的線程開始執(zhí)行handleLaunchActivity(),最主要的邏輯在performLaunchActivity:
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
?? ActivityInfo aInfo = r.activityInfo;
?? if (r.packageInfo == null) {
? ? ?? r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
? ? ? ? ? ? ?? Context.CONTEXT_INCLUDE_CODE);
?? }
?? ContextImpl appContext = createBaseContextForActivity(r);? //創(chuàng)建ContextImpl對(duì)象實(shí)例
?? Activity activity = null;
?? try {
? ? ?? java.lang.ClassLoader cl = appContext.getClassLoader();
? ? ?? activity = mInstrumentation.newActivity( ? ? ? ? ? ?? //Activity對(duì)象創(chuàng)建
? ? ? ? ? ? ?? cl, component.getClassName(), r.intent);
? ? ?? StrictMode.incrementExpectedActivityCount(activity.getClass());
? ? ?? r.intent.setExtrasClassLoader(cl);
? ? ?? r.intent.prepareToEnterProcess();
? ? ?? if (r.state != null) {
? ? ? ? ?? r.state.setClassLoader(cl);
? ? ?? }
?? } catch (Exception e) {
? ? ?? if (!mInstrumentation.onException(activity, e)) {
? ? ? ? ?? throw new RuntimeException(
? ? ? ? ? ? ?? "Unable to instantiate activity " + component
? ? ? ? ? ? ?? + ": " + e.toString(), e);
? ? ?? }
?? }
?? try {
? ? ?? Application app = r.packageInfo.makeApplication(false, mInstrumentation); //應(yīng)用已經(jīng)創(chuàng)建過Application了,返回之前的對(duì)象
? ? ?? if (activity != null) {
? ? ? ? ?? appContext.setOuterContext(activity);
? ? ? ? ?? activity.attach(appContext, this, getInstrumentation(), r.token, ? //初始化activity
? ? ? ? ? ? ? ? ?? r.ident, app, r.intent, r.activityInfo, title, r.parent,
? ? ? ? ? ? ? ? ?? r.embeddedID, r.lastNonConfigurationInstances, config,
? ? ? ? ? ? ? ? ?? r.referrer, r.voiceInteractor, window, r.configCallback);
? ? ? ? ?? if (r.isPersistable()) {
? ? ? ? ? ? ?? mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);? //oncreate調(diào)用時(shí)機(jī)
? ? ? ? ?? } else {
? ? ? ? ? ? ?? mInstrumentation.callActivityOnCreate(activity, r.state);
? ? ? ? ?? }
? ? ? ? ?? if (!r.activity.mFinished) {
? ? ? ? ? ? ?? if (r.isPersistable()) {
? ? ? ? ? ? ? ? ?? if (r.state != null || r.persistentState != null) {
? ? ? ? ? ? ? ? ? ? ?? mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state, //如果之前保存了數(shù)據(jù),可以在此恢復(fù)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? r.persistentState);
? ? ? ? ? ? ? ? ?? }
? ? ? ? ? ? ?? } else if (r.state != null) {
? ? ? ? ? ? ? ? ?? mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
? ? ? ? ? ? ?? }
? ? ? ? ?? }
? ? ?? }
?? return activity;
}
? 至于Activity的生命周期后面怎么走的,這里不在乎,我們只看Context實(shí)例化過程。同樣的,這里也會(huì)創(chuàng)建ContextImpl對(duì)象,在Activity對(duì)象創(chuàng)建后,調(diào)用Attach(),這個(gè)函數(shù)挺重要的,我們看看都干了什么:
final void attach(Context context, ActivityThread aThread,
? ? ?? Instrumentation instr, IBinder token, int ident,
? ? ?? Application application, Intent intent, ActivityInfo info,
? ? ?? CharSequence title, Activity parent, String id,
? ? ?? NonConfigurationInstances lastNonConfigurationInstances,
? ? ?? Configuration config, String referrer, IVoiceInteractor voiceInteractor,
? ? ?? Window window, ActivityConfigCallback activityConfigCallback) {
?? attachBaseContext(context); ? //同樣的,會(huì)調(diào)用此函數(shù)為ContextWrapper中的mBase對(duì)象賦值一個(gè)創(chuàng)建的ContextImpl對(duì)象
?? mWindow = new PhoneWindow(this, window, activityConfigCallback);? //創(chuàng)建PhoneWindow,這是對(duì)window操作的一系列操作的封裝
?? mWindow.setWindowControllerCallback(this);
?? mWindow.setCallback(this); ? ? ? ? ? ? ? ? ?? //設(shè)置callback是這個(gè)activity,有window相關(guān)的變化可以通知到這個(gè)activity
?? mWindow.setOnWindowDismissedCallback(this);
?? mWindow.getLayoutInflater().setPrivateFactory(this);
?? if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
? ? ?? mWindow.setSoftInputMode(info.softInputMode);
?? }
?? mUiThread = Thread.currentThread();
?? mMainThread = aThread;
?? mInstrumentation = instr;
?? mToken = token;
?? mIdent = ident;
?? mApplication = application;
?? mIntent = intent;
?? mReferrer = referrer;
?? mComponent = intent.getComponent();
?? mActivityInfo = info;
?? mTitle = title;
?? mParent = parent;
?? mEmbeddedID = id;
?? mWindow.setWindowManager( ? ? ? ? ? ?
? ? ? ? ?? (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
? ? ? ? ?? mToken, mComponent.flattenToString(),
? ? ? ? ?? (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
?? if (mParent != null) {
? ? ?? mWindow.setContainer(mParent.getWindow());
?? }
?? mWindowManager = mWindow.getWindowManager();
?? mCurrentConfig = config;
?? mWindow.setColorMode(info.colorMode);
}
? 在attach函數(shù)中,也會(huì)為ContextWrapper中的mBase對(duì)象賦值一個(gè)ContextImpl對(duì)象,我們這里也能猜想到Service的創(chuàng)建估計(jì)也會(huì)有這個(gè)過程,而事實(shí)上Service的創(chuàng)建差不多也是這個(gè)過程,所以不再贅述了。
? ? 我們可以知道Context例的實(shí)例化都是在我們?cè)贏pplication,Activity和Service創(chuàng)建的時(shí)候會(huì)實(shí)例化,而這些組件的父類都是ContextWrapper,所以在創(chuàng)建的時(shí)候還會(huì)先創(chuàng)建一個(gè)ContextImpl類對(duì)象,然后給自己的父類mBase變量賦值,既然如此,Context的引用對(duì)應(yīng)的就是Application,Activity和Service了,Context的用處就是提供了一組抽象的函數(shù),讓子類去相對(duì)應(yīng)的實(shí)現(xiàn),當(dāng)你持有一個(gè)Context引用的時(shí)候,你可以通過這個(gè)引用去獲取相對(duì)應(yīng)組件的信息。比如持有一個(gè)Activity的Context引用,你可以在別的地方調(diào)用startActivity()去啟動(dòng)一個(gè)新的activity。
總結(jié):
? 1.Context是抽象類,所以實(shí)例化要在子類中,Application,Service,Activity是我們實(shí)例化的地方,一般應(yīng)用創(chuàng)建會(huì)實(shí)例化一個(gè)Application類,Service和Activity則是在startService和StartActivity被調(diào)用的時(shí)候會(huì)實(shí)例化,它們都會(huì)創(chuàng)建一個(gè)ContextImpl類實(shí)例,給自己的父類ContextWrapper的mBase變量賦值。
? 2.Context是組件中通用操作的一組集合,當(dāng)具體的子類實(shí)例化后,可以在別的地方通過保存一個(gè)Context引用去獲取信息和通用操作等,也就是說,我們可以通過這個(gè)引用去獲取到這個(gè)應(yīng)用中的重要信息以及這個(gè)應(yīng)用的通用操作。