從源碼的角度淺談Activity躯枢、Window、View之間的關(guān)系

序言:很多人都會用Activity槐臀、Window锄蹂、View,但是你知道他們是怎樣加載出來并呈現(xiàn)在你眼前的嗎水慨?你知道他們之間有著鮮為人知的關(guān)系嗎得糜?

image

講個很簡單的例子,這一天天氣甚好晰洒,小明外出寫生朝抖,小明背了一包東西,畫板啊欢顷,紙啊槽棍,筆啊什么的,然后小明找了一處風(fēng)景甚好的地方抬驴,從包里拿出畫板炼七,紙,筆然后開始畫畫布持,不一會兒小明就畫完了一幅風(fēng)景圖豌拙。在這個例子當(dāng)中,畫板就好比Activity题暖,紙就好比Window按傅,而筆就是View捉超,我們所看到的就是這幅畫,是通過筆一點(diǎn)一點(diǎn)畫出來的唯绍,在哪里畫呢拼岳?當(dāng)然是紙上了,而最終承載這幅畫的東西就是畫板了况芒。這么說可能不太生動惜纸,下面,我們從源碼的角度來看看這三者的關(guān)系绝骚。

Activity的創(chuàng)建過程

我們都知道耐版,Activity啟動的時候是從ActivityThread中的Handler中發(fā)起的,然后經(jīng)過handlerLauncher等一系列方法压汪,如果還不知道的話可以去參考我之前寫的一步一步帶你探索Activity的啟動流程

ActivityThread類:

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {

    ...
    WindowManagerGlobal.initialize();
    Activity a = performLaunchActivity(r, customIntent);
    ...
}

在這里先調(diào)用了WindowManagerGlobal中的初始化方法初始化了WindowManagerService粪牲,看名字大概就能知道這是一個WindowManager的服務(wù),通過這個服務(wù)可以對頁面進(jìn)行操作止剖;然后通過調(diào)用performLaunchActivity方法生成了一個Activity腺阳。

Window的創(chuàng)建過程

上面通過performLaunchActivity方法生成了一個Activity,我們來看看是怎樣生成的:

ActivityThread類:

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {

    ...
    Activity activity = null;
    try {
        activity = mInstrumentation.newActivity(cl, 
                component.getClassName(), r.intent);
    } catch (Exception e) {
        ...
    }
    ...
    
    if (activity != null) {
        activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback);
    }

    ...
}

在這個方法中滴须,通過newActivity這個方法(反射)來生成了一個Activity舌狗,生成好了Activity之后就調(diào)用Activity中的attach方法,來看一下這個方法里面干了些什么:

final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor,
            Window window, ActivityConfigCallback activityConfigCallback) {
            
        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
            mWindow.setSoftInputMode(info.softInputMode);
        }
        if (info.uiOptions != 0) {
            mWindow.setUiOptions(info.uiOptions);
        }           
}

果然扔水,在Activityattach方法中創(chuàng)建了一個Window痛侍,這個Window就是我們經(jīng)常聽到的PhoneWindow

View的創(chuàng)建過程

我們大膽的猜測一下,View應(yīng)該是被添加到Window中的魔市,那么我們來看一下主届,到底是怎樣添加的呢?上面說到在handlerLauncher中調(diào)用了performLaunchActivity方法待德,源碼中還調(diào)用了handleResumeActivity方法君丁,這個方法是在生命周期onCreate之后,onResume之前調(diào)用的将宪,我們來看一下在這個方法中干了些什么:

final void handleResumeActivity(IBinder token,
            boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
    
    ...
    r = performResumeActivity(token, clearHide, reason);
    ...
    if (r.window == null && !a.mFinished && willBeVisible) {
         r.window = r.activity.getWindow();
         View decor = r.window.getDecorView();
         decor.setVisibility(View.INVISIBLE);
         ViewManager wm = a.getWindowManager();
         WindowManager.LayoutParams l = r.window.getAttributes();
         a.mDecor = decor;
         
         ...
         wm.addView(decor, l);
         ...
    }           
}

這里會先獲取一個WindowDecorView绘闷,然后拿到ViewManagerWindowManager的父類),然后調(diào)用addView方法较坛,ViewManagerWindowManager都是接口印蔗,那么我們只要到他的實(shí)現(xiàn)類WindowManagerImpl中去找addView方法就可以了:

    @Override
    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyDefaultToken(params);
        mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
    }

這個mGlobal就是我們之前的WindowManagerGlobal,看到這里相信大家應(yīng)該有點(diǎn)眉目了吧丑勤,最終是由這貨負(fù)責(zé)把DecorView添加到Window中华嘹,在WindowManagerGlobal中的addView方法中還會初始化ViewRootImpl,有興趣的可以自行看源碼了解一下

XML中的View是如何添加到DecorView中的這個也不在這里分析了法竞,可以參考我之前寫的一步一步帶你解析setContentView源碼

總結(jié)

啥也不說了耙厚,上圖

image
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末强挫,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子薛躬,更是在濱河造成了極大的恐慌俯渤,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件型宝,死亡現(xiàn)場離奇詭異稠诲,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)诡曙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來略水,“玉大人价卤,你說我怎么就攤上這事≡ɡ裕” “怎么了慎璧?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長跨释。 經(jīng)常有香客問我胸私,道長,這世上最難降的妖魔是什么鳖谈? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任岁疼,我火速辦了婚禮,結(jié)果婚禮上缆娃,老公的妹妹穿的比我還像新娘捷绒。我一直安慰自己,他們只是感情好贯要,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布暖侨。 她就那樣靜靜地躺著,像睡著了一般崇渗。 火紅的嫁衣襯著肌膚如雪字逗。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天宅广,我揣著相機(jī)與錄音葫掉,去河邊找鬼。 笑死乘碑,一個胖子當(dāng)著我的面吹牛挖息,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播兽肤,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼套腹,長吁一口氣:“原來是場噩夢啊……” “哼绪抛!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起电禀,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤幢码,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后尖飞,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體症副,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年政基,在試婚紗的時候發(fā)現(xiàn)自己被綠了贞铣。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡沮明,死狀恐怖辕坝,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情荐健,我是刑警寧澤酱畅,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站江场,受9級特大地震影響纺酸,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜址否,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一餐蔬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧在张,春花似錦用含、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至瘟斜,卻和暖如春缸夹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背螺句。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工虽惭, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蛇尚。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓芽唇,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子匆笤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評論 2 355

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