前言
電話(huà)面試時(shí)被人問(wèn)到了Service能否啟動(dòng)Activity,由于做到相關(guān)功能所以輕松答了出來(lái)。但是面試官早有預(yù)料,他的下一個(gè)問(wèn)題就是Service和Activity都是繼承Context的,那么它們的Context有什么區(qū)別嗎?于是,誕生了這篇文章。
從源碼中找答案
看下Activity和Service繼承是哪個(gè)Context:


Activity繼承的ContextThemeWrapper又是什么東西來(lái)的,點(diǎn)擊進(jìn)去一看:

原來(lái)它也是繼承ContextWrapper,然后從注釋來(lái)上看該類(lèi)內(nèi)部包含了主題Theme相關(guān)的東西。說(shuō)到主題,還記得AndroidManifest.xml里面給Activity設(shè)置android:theme屬性嗎?這個(gè)應(yīng)該就是他們的Context不同之處了,Service運(yùn)行在后臺(tái),它沒(méi)有界面就不需要主題屬性,但是Activity運(yùn)行在前臺(tái)的界面,它需要一個(gè)界面的主題屬性。
Context繼承關(guān)系
本來(lái)到上面就已經(jīng)足夠應(yīng)對(duì)面試官這個(gè)問(wèn)題了,但是這引起我的好奇心,Context到底有哪些子類(lèi)是我們平時(shí)經(jīng)常用到的?這里我通過(guò)AS查詢(xún)子類(lèi)的方法將Context繼承關(guān)系畫(huà)了出來(lái)。

Context主要就兩個(gè)子類(lèi),ContextImpl它真正實(shí)現(xiàn)了Context里面全部方法,ContextWrapper構(gòu)造函數(shù)中有一個(gè)Context的對(duì)象,同時(shí)ContextWrapper中提供了attachBaseContext(),這個(gè)方法用于傳入一個(gè)真正的Context對(duì)象(ContextImpl的實(shí)現(xiàn)對(duì)象)。
Context使用場(chǎng)景
我們知道四大組件中都有Context,那么它們中的Context分別的使用場(chǎng)景是什么呢?為了避免一個(gè)坑掉兩次,我決定再深入了解一下。先來(lái)看一張網(wǎng)上流傳很久的圖:

這里說(shuō)明一下吧:
1:?jiǎn)?dòng)Activity在這些類(lèi)中是可以的,但是需要?jiǎng)?chuàng)建一個(gè)新的task或者是Context是從Activity中獲取的。什么叫做在Activity中獲取Context呢?就拿BroadcastReceiver說(shuō)明一下好了。
BroadcastReceiver有動(dòng)態(tài)注冊(cè)和靜態(tài)注冊(cè)兩種方式,如果你是在Activity動(dòng)態(tài)注冊(cè)廣播,那么在廣播的onReceive(Context context, Intent intent)獲取到Cotnext對(duì)象就是來(lái)自Activity,那么不僅可以很方便啟動(dòng)Activity,也可以啟動(dòng)Dialog(上面的圖在這方面其實(shí)不夠嚴(yán)謹(jǐn)?shù)?。
如果你的BroadcastReceiver是在清單文件中靜態(tài)注冊(cè)的,那么獲取到Cotnext對(duì)象就是ReceiverRestrictedContext,它啟動(dòng)Activity就是需要setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)來(lái)設(shè)置一個(gè)任務(wù)棧了。同時(shí)ReceiverRestrictedContext也只能啟動(dòng)SystemAlert類(lèi)型的Dialog,而我們常用的Dialog都得依附一個(gè)Activity的Context上面。
2:在這些類(lèi)中去layout inflate是合法的,但是會(huì)使用系統(tǒng)默認(rèn)的主題樣式,如果你自定義了某些樣式可能不會(huì)被使用;
3:在Receiver為null時(shí)允許,在4.2或以上的版本中,用于獲取黏性廣播( sticky broadcast)的當(dāng)前值。(感覺(jué)日常開(kāi)發(fā)基本用不到);
總結(jié)
通過(guò)這次的學(xué)習(xí),我對(duì)Context有了更深入的了解。我們?nèi)粘i_(kāi)發(fā)要經(jīng)常用到Context,但是Context也有各種各樣的限值,只有明白了這些,我們才可以躲開(kāi)一些不必要的坑。