Context的字面含義是上下文環(huán)境。應用的上層代碼通過Context類提供的接口來操作Android的4大組件和資源。在Android的應用程序中,Context無處不在,很多接口都要求用Context對象作為參數(shù)。
Android的應用本質上是一個4大組件加上資源文件的容器,但是,這些組件的使用方式各不相同,而且比較復雜,Context類的作用就是把這些細節(jié)都封裝起來,這樣更方便開發(fā)人員使用它們。因此,可以把Context看作是整個框架的操作接口。
在Android應用中,從Context中派生的類的關系如下:

Context是一個抽象類,定義了接口,它的實現(xiàn)類是ContextImpl類。
ContextWrapper是Context的派生類,它實現(xiàn)了Context類的接口。但是ContextWrapper類所有方法的實現(xiàn)只是轉調其成員變量mBase的方法。mBase本身也是Context對象,其類型是ContextImpl,因此,ContextImpl類才是Context類真正的實現(xiàn)。這種設計模式稱為代理模式或包裝者模式。這種設計模式的好處是把接口和實現(xiàn)分離,可以動態(tài)地切換多種實現(xiàn)。
ContextImpl類是Context的真正實現(xiàn)類,它集成了應用框架的一些核心對象,如ActivityThread對象。
Activity,Service,Application都是從ContextWrapper類派生出來的。Activity是通過ContextThemeWrapper類間接派生的,這樣實現(xiàn)的目的是為了實現(xiàn)Activity中單獨的Theme。一個應用中可以有一套全局的Theme,同時每個Activity還可以有自己的Theme。ContextWrapper類的成員變量中保存Theme資源和Resource資源。這樣它的派生類Activity就能有獨立的Theme。
Application的Context和Activity的Context的區(qū)別?
Activity、Service和Application這三種類型的Context都是可以通用的。不過有幾種場景比較特殊,比如啟動Activity,還有彈出Dialog。出于安全原因的考慮,Android是不允許Activity或Dialog憑空出現(xiàn)的,一個Activity的啟動必須要建立在另一個Activity的基礎之上,也就是以此形成的返回棧。而Dialog則必須在一個Activity上面彈出(除非是System Alert類型的Dialog),因此在這種場景下,我們只能使用Activity類型的Context,否則將會出錯。
在應用程序中Context的具體實現(xiàn)子類就是:Activity,Service,Application。那么Context數(shù)量=Activity數(shù)量+Service數(shù)量+1。
Broadcast Receiver,Content Provider并不是Context的子類,他們所持有的Context都是其他地方傳過去的,所以并不計入Context總數(shù)。
如何獲取Context?
通常我們想要獲取Context對象,主要有以下四種方法
1) View.getContext:返回當前View對象的Context對象,通常是當前正在展示的Activity對象。
2) Activity.getApplicationContext:獲取當前Activity所在的(應用)進程的Context對象,通常我們使用Context對象時,要優(yōu)先考慮這個全局的進程Context。
3) ContextWrapper.getBaseContext():用來獲取一個ContextWrapper進行裝飾之前的Context,可以使用這個方法,這個方法在實際開發(fā)中使用并不多,也不建議使用。
4) Activity.this:返回當前的Activity實例,如果是UI控件需要使用Activity作為Context對象,但是默認的Toast實際上使用ApplicationContext也可以。
5) getApplication()和getApplicationContext():它們得到的是同一個對象。getApplication()只能在Activity和Service中得到。在BroadcastReciver必須使用getApplicationContext()。