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

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

簡(jiǎn)介

我們先看google官方的說明

/**
 * 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胯陋、通過它我們可以獲取應(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)系樹的韭赘。
讓我們看一張類圖缩滨,相信看完這個(gè)類圖大家就知道context在我們的應(yīng)用中是什么樣子的地位:

context繼承關(guān)系圖

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

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

可見脉漏,我們的每個(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ī)

通過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ī)

通過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)的是碴犬,通過對(duì)ContextImp的分析可知,其方法的大多數(shù)操作都是直接調(diào)用其屬性mPackageInfo(該屬性類型為PackageInfo)的相關(guān)方法而來梆暮。這說明ContextImp是一種輕量級(jí)類服协,而PackageInfo才是真正重量級(jí)的類。而一個(gè)App里的所有ContextIml實(shí)例啦粹,都對(duì)應(yīng)同一個(gè)packageInfo對(duì)象


本文作者:Jerey_Jobs

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

github地址:Jerey_Jobs

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末偿荷,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子唠椭,更是在濱河造成了極大的恐慌跳纳,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,427評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件贪嫂,死亡現(xiàn)場(chǎng)離奇詭異寺庄,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)力崇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門斗塘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人餐曹,你說我怎么就攤上這事逛拱。” “怎么了台猴?”我有些...
    開封第一講書人閱讀 165,747評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵朽合,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我饱狂,道長(zhǎng)曹步,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,939評(píng)論 1 295
  • 正文 為了忘掉前任休讳,我火速辦了婚禮讲婚,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘俊柔。我一直安慰自己筹麸,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評(píng)論 6 392
  • 文/花漫 我一把揭開白布雏婶。 她就那樣靜靜地躺著物赶,像睡著了一般。 火紅的嫁衣襯著肌膚如雪留晚。 梳的紋絲不亂的頭發(fā)上酵紫,一...
    開封第一講書人閱讀 51,737評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼奖地。 笑死橄唬,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的参歹。 我是一名探鬼主播仰楚,決...
    沈念sama閱讀 40,448評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼泽示!你這毒婦竟也來了缸血?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,352評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤械筛,失蹤者是張志新(化名)和其女友劉穎捎泻,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體埋哟,經(jīng)...
    沈念sama閱讀 45,834評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡笆豁,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了赤赊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片闯狱。...
    茶點(diǎn)故事閱讀 40,133評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖抛计,靈堂內(nèi)的尸體忽然破棺而出哄孤,到底是詐尸還是另有隱情,我是刑警寧澤吹截,帶...
    沈念sama閱讀 35,815評(píng)論 5 346
  • 正文 年R本政府宣布瘦陈,位于F島的核電站,受9級(jí)特大地震影響波俄,放射性物質(zhì)發(fā)生泄漏晨逝。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評(píng)論 3 331
  • 文/蒙蒙 一懦铺、第九天 我趴在偏房一處隱蔽的房頂上張望捉貌。 院中可真熱鬧,春花似錦冬念、人聲如沸趁窃。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)醒陆。三九已至,卻和暖如春叔汁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工据块, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留码邻,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,398評(píng)論 3 373
  • 正文 我出身青樓另假,卻偏偏與公主長(zhǎng)得像像屋,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子边篮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評(píng)論 2 355

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