Context是場(chǎng)景的意思讽坏,android有什么場(chǎng)景呢?最常用的場(chǎng)景就是Activity了网梢。Context讓對(duì)象要一個(gè)共同的抓手震缭。例如一個(gè)Activity叫中國(guó),那么里面的對(duì)象中國(guó)人就都要一個(gè)共同抓手國(guó)家战虏。
下面是系統(tǒng)Context的類圖
從上面的圖可以看到拣宰,Activity和ContextImpl并沒有直接的繼承關(guān)系,而我們知道Activity的主要處理邏輯都在ContextImpl里面烦感。下面我們看看是怎么一步步引用到ContextImpl的巡社。
以Activity獲取系統(tǒng)服務(wù)PowerManager為例簡(jiǎn)單說一下
源碼路徑/frameworks/base/core/java/android/app/Activity.java
在Activity的oncreate中
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
}
進(jìn)入Activity的getSystemService
@Override
public Object getSystemService(@ServiceName @NonNull String name) {
if (getBaseContext() == null) {
throw new IllegalStateException(
"System services not available to Activities before onCreate()");
}
if (WINDOW_SERVICE.equals(name)) {
return mWindowManager;
} else if (SEARCH_SERVICE.equals(name)) {
ensureSearchManager();
return mSearchManager;
}
return super.getSystemService(name);
}
super.getSystemService(name)會(huì)進(jìn)入父類的getSystemService方法,父類由上面的類圖可以知道是ContextThemeWrapper
源碼路徑:/frameworks/base/core/java/android/view/ContextThemeWrapper.java
@Override public Object getSystemService(String name) {
if (LAYOUT_INFLATER_SERVICE.equals(name)) {
if (mInflater == null) {
mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);
}
return mInflater;
}
return getBaseContext().getSystemService(name);
}
如果不是LAYOUT_INFLATER_SERVICE的話手趣,會(huì)進(jìn)入getBaseContext().getSystemService(name);
查看getBaseContext()方法晌该,該方法在ContextThemeWrapper的父類ContextWrapper中定義
Context mBase;
public Context getBaseContext() {
return mBase;
}
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
可以看到返回mBase變量,進(jìn)而調(diào)用mBase的getSystemService方法獲取到系統(tǒng)绿渣,所以現(xiàn)在的關(guān)鍵是查看這個(gè)mBase是何方神圣朝群。
這個(gè)變量是通過函數(shù)attachBaseContext賦值,這個(gè)函數(shù)在Activity類被attach方法調(diào)用
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) {
.......
attachBaseContext(context);
......
}
這個(gè)方法在ActivityThread類中的performLaunchActivity方法調(diào)用中符,這個(gè)方法用于啟動(dòng)Activity姜胖,所以mBase對(duì)象是在應(yīng)用啟動(dòng)的時(shí)候初始化的。
源碼路徑:/frameworks/base/core/java/android/app/ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
......
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);
........
}
馬上就能知道這個(gè)mBase對(duì)象是什么了淀散,看看createBaseContextForActivity函數(shù)
private Context createBaseContextForActivity(ActivityClientRecord r, final Activity activity) {
..........
ContextImpl appContext = ContextImpl.createActivityContext(
this, r.packageInfo, displayId, r.overrideConfig);
Context baseContext = appContext;
..............
return baseContext;
}
看到了吧右莱,createBaseContextForActivity返回的是ContextImpl類型的對(duì)象。所以mBase對(duì)象類型就是ContextImpl 档插。Activity成功與ContextImpl 聯(lián)系起來了B选!
上面的說明有點(diǎn)逆向郭膛,用時(shí)間順序來說的話晨抡,就是應(yīng)用啟動(dòng)過程在performLaunchActivity中創(chuàng)建了ContextImpl類型的mBase變量,然后將mBase attach到Activity中则剃,然后應(yīng)用調(diào)用getSystemService的時(shí)候凄诞,會(huì)逐步調(diào)用到mBase的getSystemService方法,即ContextImpl類的getSystemService方法忍级。