總共可分為 Activity context卸夕、Application context、ContextImpl(BaseContext) 這些
1. Activity Context
- android.app.ActivityThread#performLaunchActivity
- android.app.Instrumentation#newActivity 創(chuàng)建Activity實(shí)例婆瓜,直接調(diào)用Activity的無(wú)參構(gòu)造
- android.app.ActivityThread#createBaseContextForActivity 為Activity創(chuàng)建BaseContext快集。
- android.app.ContextImpl#createActivityContext 創(chuàng)建ContextImpl實(shí)例
設(shè)置ContextImpl的OuterContext為Activity - android.app.Activity#attach->android.content.ContextWrapper#attachBaseContext 為Activity的BaseContext賦值;
因此Activity的BaseContext每次都是新的廉白。
2. Application Context
- android.app.LoadedApk#makeApplication个初,首先判斷Application實(shí)例是否存在,如果存在則直接返回蒙秒,不存在繼續(xù)下面步驟勃黍。
- 首先調(diào)用 android.app.ContextImpl#createAppContext 創(chuàng)建一個(gè)ContextImpl實(shí)例;
- 調(diào)用 android.app.Instrumentation#newApplication 創(chuàng)建一個(gè)Application實(shí)例晕讲;
- 在調(diào)用 newApplication 之前覆获,調(diào)用 ContextImpl.createAppContext() 方法生成 ContextImpl
- 調(diào)用 android.app.Application#attach->android.content.ContextWrapper#attachBaseContext 為Application的BaseContext賦值;
- 最后調(diào)用 android.app.ContextImpl#setOuterContext 將Application實(shí)例賦值給ContextImpl的mOuterContext瓢省,這個(gè)mOuterContext的作用:
startActivity時(shí)弄息,如果是ActivityContext的話,就不需要加 FLAG_ACTIVITY_NEW_TASK 標(biāo)記之類的
創(chuàng)建部分SystemService(如:android.content.Context#NOTIFICATION_SERVICE)時(shí)勤婚,也會(huì)用到mOuterContext摹量。具體參考ContextImpl的static塊。 - 因?yàn)橐粋€(gè)進(jìn)程中只會(huì)有 Application的一個(gè)實(shí)例,因此Application的BaseContext也只會(huì)存在一個(gè)缨称。
3. 總結(jié)
- Application 和 Activity 都繼承自 ContextWapper凝果,當(dāng)調(diào)用 ContextWapper 內(nèi)的方法時(shí),就是調(diào)用 ContextImpl 內(nèi)的方法睦尽,具體的實(shí)現(xiàn)都在這里器净。
- 在調(diào)用 getBaseContext() 方法時(shí),這里返回的就是 ContextImpl 對(duì)象当凡。
- 所以山害,每一個(gè) Activity / Application 都能轉(zhuǎn)換為 ContextImpl 對(duì)象。
- Application的BaseContext只會(huì)存在一個(gè)沿量,而Activity和Service的BaseContext每次都是新的.
4. 其他
- 原生 Application 創(chuàng)建新的 Context
Context mContext = this.getBaseContext().createPackageContext(mPackageName, Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);