Android是一個開源系統,至少說是大部分開源的,源代碼的學習對於咱們學習Android幫助很是大,可能不少人看看源碼時感受代碼太多了,不知道從何開始,今天我就從基本的部分開始跟你們一塊兒學習Android源碼。
聲明:本篇以及之後Android源碼分析是基於Android-7.1.2_r11(7.1最終版代碼)源碼進行分析。若是以後切換會進行聲明。但願對照源碼學習的要找對應版本進行查看。java
在開始介紹Context前咱們先看一張Android系統框架層的圖:android
從上面圖能夠看到Android系統主要分爲五層:應用層,應用框架層,Native庫和運行環境,硬件抽象層和Linux內核層。本章不重點講Android系統框架,只是開始給你們展現一下,有個瞭解,咱們先從Framework層開始學習,首先學習Context,下面進入正題。數據庫
作Android開發的朋友在開發過程當中時刻用到Context,那麼Context究竟是什麼,究竟是作什麼的咱們詳細分析一下。源碼中解釋Context是一個面向應用全局信息的接口,那麼我看看哪些信息與Context有關:微信
主要的信息關聯就是這些,還有一些不經常使用的或者廢棄的沒有再展現,有興趣本身看看源碼,官方解釋很清晰。上面有個獲取系統服務,咱們下面把全部的系統服務列舉一下(前面是服務,後面是獲取服務的名稱):網絡
上面這些服務,你能夠經過Context.getSystemService(Context.名稱)直接獲取,而後進行操做。app
首先看一下類圖關係:框架
1.ContextImpl、ContextWrapper與Context的關係ide
Context是一個靜態類,ContextImpl和ContextWrapper都繼承了Context,也就是都實現了Context的靜態方法,可是,從代碼中咱們看到ContextImpl是Context靜態方法的詳細實現類,而ContextWrapper是調用了mBase對應的方法,而mBase是Context,從代碼跟蹤看mBase其實就是ContextImpl,所以ContextWrapper最終是調用ContextImpl中的實現方法。也就是說咱們調用的Context中的任何方法都是在ContextImpl中處理的,所以咱們在跟蹤代碼時只須要去ContextImpl中查看對應方法處理就行了。上面只是介紹,下面咱們根據具體代碼來分析一下到底怎麼實現的。函數
從ContextWrapper代碼中咱們能夠看到(不貼所有代碼了),只有構造函數、attachBaseContext方法以及getBaseContext方法不是複寫方法,其餘方方法均爲複寫方法:oop
【ContextWrapper.java】
Context mBase;
public ContextWrapper(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. */
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
/** * @return the base context as set by the constructor or setBaseContext */
public Context getBaseContext() {
return mBase;
}複製代碼
咱們能夠看到只有構造函數和attachBaseContext方法傳入了mBase,那麼從attachBaseContext方法中咱們看到若是mBase存在又調用了該方法就會拋出異常,所以咱們知道若是調用了該方法,那麼構造函數不能傳入這個值,咱們看一下哪些地方調用了這個attachBaseContext方法,由代碼能夠看到Application、activity和service均調用了這個方法,首先咱們來看Application中的代碼:
【Application.java】
/** * @hide */
/* package */ final void attach(Context context) {
attachBaseContext(context);
mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}複製代碼
Application中的attach方法中調用了attachBaseContext方法,參數context也是經過attach方法傳入的,那麼咱們再跟蹤這個attach方法:
是在Instrumentation類中調用的:
【Instrumentation.java】
static public Application newApplication(Class<?> clazz, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
Application app = (Application)clazz.newInstance();
app.attach(context);
return app;
}複製代碼
上面方法調用地方是:
【Instrumentation.java】
public Application newApplication(ClassLoader cl, String className, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return newApplication(cl.loadClass(className), context);
}複製代碼
從代碼能夠看到是在new Application時調用的,那麼咱們接着看哪裏調用了這個方法:
【LoadedApk.java】
public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) {
...
try {
...
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) {
...
}
...
return app;
}複製代碼
上面方法是在LoadedApk類中調用的,咱們先不分析這個類,後續咱們會詳細講這個過程,咱們先分析上面這段代碼,咱們看到這裏面經過調用ContextImpl.createAppContext方法來建立ContextImpl,而後將參數傳入newApplication方法,所以咱們看到上面的mBase就是ContextImpl,那麼還有Activity和Service.咱們先分析Service,由於從關係圖能夠看到Service和Application都是直接繼承ContextWrapper,而Activity則是繼承ContextThemeWrapper,ContextThemeWrapper繼承ContextWrapper。
【Service.java】
public final void attach( Context context, ActivityThread thread, String className, IBinder token, Application application, Object activityManager) {
attachBaseContext(context);
...
}複製代碼
attachBaseContext方法是在Service中的attach方法中調用的,接着看attach方法的調用:
【ActivityThread.java】
private void handleCreateService(CreateServiceData data) {
...
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
Application app = packageInfo.makeApplication(false, mInstrumentation);
service.attach(context, this, data.info.name, data.token, app,
ActivityManagerNative.getDefault());
service.onCreate();
...
}複製代碼
在這裏咱們看到傳入的context就是ContextImpl,從而獲得驗證,下面咱們還看到service.onCreate方法,咱們看到了先調用attach方法而後調用onCreate方法。
最後咱們看一下Activity,從上面關係圖咱們看到,Activity不是直接繼承ContextWrapper,而是繼承的ContextThemeWrapper,ContextThemeWrapper繼承ContextWrapper。從名字咱們能夠看到ContextThemeWrapper包含主題的信息,其實不難理解,四大組件只有Activity是帶界面的,其餘都是沒有界面的,所以Activity須要主題信息來顯示不一樣的界面效果。在ContextThemeWrapper中咱們看到複寫了attachBaseContext方法,方法中只有一行代碼就是調用父類的attachBaseContext方法。以下所示:
【ContextThemeWrapper.java】
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(newBase);
}複製代碼
在Activity中只有一個方法中調用了該方法,看代碼:
【Activity.java】
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) {
attachBaseContext(context);
...
}複製代碼
咱們接着追蹤attach方法,看代碼:
【ActivitThread.java】
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
if (activity != null) {
Context appContext = createBaseContextForActivity(r, activity);
...
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window);
...
}
...
return activity;
}複製代碼
方法performLaunchActivity實際上是啓動Activity的方法,這裏咱們暫時不講,後續咱們會詳細講解,咱們先理清楚Context,從上面代碼咱們能夠看到此處傳入的Context是經過createBaseContextForActivity方法建立的,那麼咱們看一下這個方法:
【ActivitThread.java】
private Context createBaseContextForActivity(ActivityClientRecord r, final Activity activity) {
...
ContextImpl appContext = ContextImpl.createActivityContext(
this, r.packageInfo, r.token, displayId, r.overrideConfig);
appContext.setOuterContext(activity);
Context baseContext = appContext;
...
return baseContext;
}複製代碼
從上面代碼我肯能夠清楚的看到baseContext是appContext賦值的,而appContext就是ContextImpl,所以Activity中的Context也是ContextImpl。到如今咱們已經搞清楚了ContextImpl、Context、ContextWrapper、ContextThemeWrapper以及Application、Service和Activity的關係,那麼之後看源碼咱們就知道與Context相關的實現方法都在ContextImpl類中,若是須要看詳細實現過程只須要去ContextImpl類中找到相應方法開始跟蹤便可。
從下一章咱們開始講解四大組件的啓動過程。
注
同步發佈:www.codemx.cn/2017/06/05/…
Android開發羣:192508518
微信公衆帳號:Code-MX
注:本文原創,轉載請註明出處,多謝。