Android開(kāi)發(fā)之什么是context

今天研究了一下Context類,對(duì)于context發(fā)現(xiàn)即熟悉又陌生。一個(gè)我們天天打交道的東西到底是什么呢,這篇文章將帶大家了解context。

簡(jiǎn)介

我們先看google官方的說(shuō)明

/**
 * Interface to global information about an application environment.  This is
 * an abstract class whose implementation is provided by
 * the Android system.  It
 * allows access to application-specific resources and classes, as well as
 * up-calls for application-level operations such as launching activities,
 * broadcasting and receiving intents, etc.
 */
public abstract class Context

從上可知一下三點(diǎn),即:
1、它描述的是一個(gè)應(yīng)用程序環(huán)境的信息,即上下文。
2、該類是一個(gè)抽象(abstract class)類,Android提供了該抽象類的具體實(shí)現(xiàn)類(后面我們會(huì)講到是ContextIml類)。
3、通過(guò)它我們可以獲取應(yīng)用程序的資源和類,也包括一些應(yīng)用級(jí)別操作,例如:?jiǎn)?dòng)一個(gè)Activity,發(fā)送廣播,接受Intent 信息 等。。

那么我們明確第一點(diǎn),context是一個(gè)抽象類,而我們平時(shí)用的context,均是其實(shí)現(xiàn),而更偉大的是, 我們的application,我們的activity,service,均在context的繼承關(guān)系樹(shù)的。
讓我們看一張類圖,相信看完這個(gè)類圖大家就知道context在我們的應(yīng)用中是什么樣子的地位:

context繼承關(guān)系圖

通過(guò)看圖,我們知道了,一個(gè)應(yīng)用程序App共有的Context數(shù)目公式為:

                 總Context實(shí)例個(gè)數(shù) = Service個(gè)數(shù) + Activity個(gè)數(shù) + 1(Application對(duì)應(yīng)的Context實(shí)例)

可見(jiàn),我們的每個(gè)Activity,Service,Application都有自己的context,那么context是什么時(shí)候傳入的呢?

Context的傳入

1.創(chuàng)建Application對(duì)象的時(shí)機(jī)

每個(gè)應(yīng)用程序在第一次啟動(dòng)時(shí),都會(huì)首先創(chuàng)建Application對(duì)象。在應(yīng)用程序啟動(dòng)Activity(startActivity)流程中,創(chuàng)建Application的時(shí)機(jī)在創(chuàng)建handleBindApplication()方法中,該函數(shù)位于 ActivityThread.java類中 ,如下:

//創(chuàng)建Application時(shí)同時(shí)創(chuàng)建的ContextIml實(shí)例  
private final void handleBindApplication(AppBindData data){  
    ...  
    ///創(chuàng)建Application對(duì)象  
    Application app = data.info.makeApplication(data.restrictedBackupMode, null);  
    ...  
}  
  
public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) {  
    ...  
    try {  
        java.lang.ClassLoader cl = getClassLoader();  
        ContextImpl appContext = new ContextImpl();    //創(chuàng)建一個(gè)ContextImpl對(duì)象實(shí)例  
        appContext.init(this, null, mActivityThread);  //初始化該ContextIml實(shí)例的相關(guān)屬性  
        ///新建一個(gè)Application對(duì)象   
        app = mActivityThread.mInstrumentation.newApplication(  
                cl, appClass, appContext);  
       appContext.setOuterContext(app);  //將該Application實(shí)例傳遞給該ContextImpl實(shí)例           
    }   
    ...  
}  

2、創(chuàng)建Activity對(duì)象的時(shí)機(jī)

通過(guò)startActivity()或startActivityForResult()請(qǐng)求啟動(dòng)一個(gè)Activity時(shí),如果系統(tǒng)檢測(cè)需要新建一個(gè)Activity對(duì)象時(shí),就會(huì)回調(diào)handleLaunchActivity()方法,該方法繼而調(diào)用performLaunchActivity()方法,去創(chuàng)建一個(gè)Activity實(shí)例,并且回調(diào)onCreate(),onStart()方法等, 函數(shù)都位于 ActivityThread.java類 ,如下:

//創(chuàng)建一個(gè)Activity實(shí)例時(shí)同時(shí)創(chuàng)建ContextIml實(shí)例  
private final void handleLaunchActivity(ActivityRecord r, Intent customIntent) {  
    ...  
    Activity a = performLaunchActivity(r, customIntent);  //啟動(dòng)一個(gè)Activity  
}  
private final Activity performLaunchActivity(ActivityRecord r, Intent customIntent) {  
    ...  
    Activity activity = null;  
    try {  
        //創(chuàng)建一個(gè)Activity對(duì)象實(shí)例  
        java.lang.ClassLoader cl = r.packageInfo.getClassLoader();  
        activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);  
    }  
    if (activity != null) {  
        ContextImpl appContext = new ContextImpl();      //創(chuàng)建一個(gè)Activity實(shí)例  
        appContext.init(r.packageInfo, r.token, this);   //初始化該ContextIml實(shí)例的相關(guān)屬性  
        appContext.setOuterContext(activity);            //將該Activity信息傳遞給該ContextImpl實(shí)例  
        ...  
    }  
    ...      
}  
 

3、創(chuàng)建Service對(duì)象的時(shí)機(jī)

通過(guò)startService或者bindService時(shí),如果系統(tǒng)檢測(cè)到需要新創(chuàng)建一個(gè)Service實(shí)例,就會(huì)回調(diào)handleCreateService()方法,完成相關(guān)數(shù)據(jù)操作。handleCreateService()函數(shù)位于 ActivityThread.java類,如下:

//創(chuàng)建一個(gè)Service實(shí)例時(shí)同時(shí)創(chuàng)建ContextIml實(shí)例  
private final void handleCreateService(CreateServiceData data){  
    ...  
    //創(chuàng)建一個(gè)Service實(shí)例  
    Service service = null;  
    try {  
        java.lang.ClassLoader cl = packageInfo.getClassLoader();  
        service = (Service) cl.loadClass(data.info.name).newInstance();  
    } catch (Exception e) {  
    }  
    ...  
    ContextImpl context = new ContextImpl(); //創(chuàng)建一個(gè)ContextImpl對(duì)象實(shí)例  
    context.init(packageInfo, null, this);   //初始化該ContextIml實(shí)例的相關(guān)屬性  
    //獲得我們之前創(chuàng)建的Application對(duì)象信息  
    Application app = packageInfo.makeApplication(false, mInstrumentation);  
    //將該Service信息傳遞給該ContextImpl實(shí)例  
    context.setOuterContext(service);  
    ...  
}  

需要強(qiáng)調(diào)一點(diǎn)的是,通過(guò)對(duì)ContextImp的分析可知,其方法的大多數(shù)操作都是直接調(diào)用其屬性mPackageInfo(該屬性類型為PackageInfo)的相關(guān)方法而來(lái)。這說(shuō)明ContextImp是一種輕量級(jí)類,而PackageInfo才是真正重量級(jí)的類。而一個(gè)App里的所有ContextIml實(shí)例,都對(duì)應(yīng)同一個(gè)packageInfo對(duì)象


本文作者:Jerey_Jobs

簡(jiǎn)書(shū)地址:Anderson大碼渣

github地址:Jerey_Jobs

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,763評(píng)論 6 539
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,238評(píng)論 3 428
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 177,823評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 63,604評(píng)論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,339評(píng)論 6 410
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,713評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,712評(píng)論 3 445
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,893評(píng)論 0 289
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,448評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,201評(píng)論 3 357
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,397評(píng)論 1 372
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,944評(píng)論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,631評(píng)論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 35,033評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 36,321評(píng)論 1 293
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,128評(píng)論 3 398
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,347評(píng)論 2 377

推薦閱讀更多精彩內(nèi)容