基于Android6.0的Activity加載View源碼分析

作者簡介? 原創(chuàng)微信公眾號郭霖 WeChat ID: guolin_blog

本篇來自程序媛fanfan_story的投稿,透過Android6.0源碼阳掐,分析了Activity加載View的過程,希望大家喜歡财骨。

fanfan_story的博客地址:

http://blog.csdn.net/zrf1335348191

認識Activity的布局

對于研究布局這種東西巡球,必須要掌握一些視圖工具壁酬,在這里推薦一個sdk查看視圖的工具sdk\tools\hierarchyviewer,隨意找一個界面去查看 activity 的 view視圖:

在這個 activity 界面中我把導航欄給隱藏了辖所,所以不存在導航欄惰说,根據(jù)這張圖的話大致可以看到一個 activity 的布局,再結(jié)合對?setContentView 的研究缘回,可以總結(jié)出 activity 的布局圖如下:

從這張 activity 的布局圖可以看到:一個 activity 對應(yīng)一個應(yīng)用窗口 mWindow吆视,應(yīng)用窗口 mWindow 包括 activity 的 頂級view是 mDecorView,mDecorView 包括 狀態(tài)欄statusbar和 導航欄navigationbar 以及要加載 activity 布局的view一一mDecorContentParent酥宴,該 view 又包括一個 標題欄titlebar 和 activity的內(nèi)容布局 contentparent啦吧。在 contentParent 中就是該 activity 的 view樹。

1. mWindow:Window對象幅虑,Window是一個抽象類丰滑,是 activity 的頂層外觀和行為的代理。會往 windowmanage 中添加該類的一個實例作為 頂層view倒庵。window 提供基本的UI代理,比如背景啊炫刷,標題區(qū)域啊擎宝,按鍵處理啊等等,Window 只有一個實現(xiàn)類 PhoneWindow浑玛,所以 mWindow對象 實際是 PhoneWindow對象绍申。當啟動一個activity的過程中會初始化一個屬于 Phonewindow 的 window對象。Phonewindow對象 的創(chuàng)建在activity 的 attach方法 中顾彰。

2. mDecor:DecorView對象极阅,繼承自 framelayout,是 window窗口 的 頂級view涨享,包含 window 的裝飾筋搏。類的定義位于 PhoneWindow.java 中

3. mDecorContentParent:DecorContentParent對象,實現(xiàn)類是 ActionbarOverlayLayout厕隧,屬于 activity 布局的 最外層view奔脐,包括標題欄和activity的內(nèi)容布局

4. mContentParent:activity 的內(nèi)容布局俄周,繼承自 ViewGroup,用來加載存放 activity 的 view樹髓迎,如果沒有標題欄峦朗,那么 mContentparent 的大小會和 mDecorContentParent 相等,以此類推

5. 導航欄:statusbar,對應(yīng)的 id 為 statusBarBackground排龄,在 PhoneWindow 中會加載波势,當 window屬性 發(fā)生改變時會刷新導航欄。但不論是導航欄和狀態(tài)欄橄维,從這個id也可以看出艰亮,PhoneWindow 只是加載他們的 background,即相當于只加載一個view的占位挣郭,先告訴應(yīng)用窗口迄埃,系統(tǒng)窗口要求將狀態(tài)欄和導航欄布局在這里,你不要占用兑障,但此時不會加載導航欄和狀態(tài)欄的view侄非,只是繪制背景而已。

6. 狀態(tài)欄:navigationbar,對應(yīng)的 id 為 navigationBarBackground流译,在 PhoneWindow 中會加載逞怨,當 window屬性 發(fā)生改變時會刷新狀態(tài)欄

7. 標題欄:titlebar,對于導航欄福澡,狀態(tài)欄和標題欄的存在與否叠赦,與 window 的屬性特征有關(guān),在加載 view 時所以會去判斷 window 的屬性特征革砸,進而決定是否要加載這三者除秀。

對 activity 的布局大致有個了解之后,就開始去分析 activity 啟動后加載view的流程

Activity加載View布局

對于 activity 的布局的加載大致分為兩部分算利,一部分是加載view册踩,另一部分是將view綁定到應(yīng)用窗口Window。其中這兩個步驟中將 view 綁定到 window 是在 啟動activity時 完成的操作效拭,是將 mDecor 綁定到 window暂吉。然后再往 mDecor 中添加 各種view。對于 activity的啟動過程 留待以后進行分析缎患,現(xiàn)在分析加載view一一始于 Activity.Java?的setContentView方法慕的,看一下加載view的流程。

可以看到代碼流程很簡單挤渔,從 Activity.java 的 setContentView方法 進入肮街,到 PhonewWindow.java 的 setContentView方法 進行一系列處理,接下來進入代碼進行分析

Activity.java 的 setContentView 方法

代碼路徑\Android\frameworks\base\core\java\android\app

源碼中對該方法的解釋是蚂蕴,從一個 layout 文件中取出 view 設(shè)置成 activity 的 content低散,該資源文件會被填充俯邓,并遍歷文件中的 所有view 添加到 activity。意思就是填充一個資源文件熔号,加載view稽鞭。做了兩件事兒:

一是 getWindow 獲取到 Window對象,然后去調(diào)用 Window 的 setContentView方法引镊。

二是 initWindowDecorActionbar()朦蕴,創(chuàng)建 actionbar對象,填充 mDecor 下的 actionbarView弟头,并把 view 加載上去(博主猜測是在 Window 的 setContentView方法 中只是填充一個 actionbar 的占位吩抓,然后 initWindowDecorActionbar() 完成 view 的加載)

重點研究第一步:getWindow().setContentView方法。

首先一個問題赴恨,為什么我要說 getWindow.setContentView 調(diào)用的是 PhoneWindow 中的setContentView方法疹娶?

解疑:查看getWindow方法:

publicWindowgetWindow() {

returnmWindow;}

返回的是 activity 的 mWindow對象,對于 mWindow對象 的創(chuàng)建也是在 Activity.java 中的 attach方法 中:

同時伦连,進入到 Window.java 中也可以看到這一點:

源碼中對于 Window類 的說明是:

Window 是一個抽象類雨饺,是最頂層的窗口的外觀和行為的代理,window 的實例應(yīng)該被作為最頂層的UI添加到 WindowManage?中惑淳。Window 提供了基本的ui额港,比如背景,標題區(qū)域歧焦,默認的按鍵處理過程等等移斩。Window 只有一個唯一的實現(xiàn)類 PhoneWindow,當需要 Window對象 時需要去初始化 PhoneWindow绢馍。

至此向瓷,對于 Activity 中的 mWindow對象 大致有了一個清晰的認識了:他是個 PhoneWindow對象,Window.java 中方法的實現(xiàn)在?PhoneWindow.java 中

PhoneWindow.java中的setContentView方法

代碼路徑\android\frameworks\base\core\java\com\android\internal\policy

先來總結(jié)一下代碼的流:

在新啟動一個 activity 時 mContentParent 還未綁定id痕貌,此時 mContentParent 為null风罩。從代碼流程圖中可以看出 setContentView 做了三件事:

installDecor 實例化 DecorView對象 和 mContentParent對象

填充 layout 文件

通知 activity 布局已經(jīng)改變

為什么說是通知 activity 布局已經(jīng)改變呢?這是因為在 Activity.java 的 attach方法 中 mWindow對象 設(shè)置了 callback 為this舵稠,所以在 getCallback 時獲取到的 cb 為當前與該 window 對應(yīng)的 activity。

PhoneWindow.java中的installDecor方法分析

實例化 DecorView對象 和 mContentParent對象

在創(chuàng)建一個 activity 時 mDecor 和 mContentParent 均為null

借助 generateDecor 方法實例化 mDecor入宦,即獲取到 activity 的 最頂級的view

借助 generateLayout 方法實例化 mContentParent對象哺徊,并且根據(jù) window 的不同 Feature 來選擇對應(yīng)的布局文件(總之,generatelayout 其實就是根據(jù)當前的 window 的特征屬性 feature 來加載內(nèi)容布局乾闰,并獲取到當前布局的 最外層view落追。也就是說

generatelayout 本質(zhì)就是根據(jù) activity 的 theme主題 來找到對應(yīng)的xml布局并且獲取到id為 content 的 ViewGroup賦給 mContentParent

獲取到 mDecorParent對象,并且根據(jù) getLocalFeature 獲取到的 Feature 來設(shè)置(這也就說明了在自定義Activity時為什么要將?getWindow.requestFeature方法 寫在 setContentView方法 之前)

對 title 進行隱藏或者是設(shè)置內(nèi)容的操作

如果需要切入切出動畫涯肩,那么就獲取到各種動畫資源

接下來對 installDecor 中某些代碼做一些分析:

mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);

用于對焦點的傳遞設(shè)置:只有當 子view 不想獲取焦點時 mDecor 才會去獲取焦點

mDecor.postOnAnimation(mInvalidatePanelMenuRunnable)

去開啟初始化menu菜單的線程

在這里說明一句轿钠,為什么 requestFeature 要寫在 setContentView 前面巢钓,這是因為在調(diào)用 setContentView 時會獲取到 window 的各種 feature 進行一些判斷設(shè)置。

PhoneWindow.java中的generateLayout方法研究

第一步:首先是獲取到 window 的布局style

TypedArraya=getWindowStyle();

第二步:獲取到各種屬性并進行 requestFeature 的設(shè)置

第三步:通過獲取到的 window 的布局去獲取 window 的各種屬性疗垛,并根據(jù) window 的各種屬性去選擇不同的 layout 的文件症汹,比如標題欄是否隱藏,window 是懸浮窗還是全屏等等問題贷腕。當然因為在3.0和4.0以及5.0對于menukey的支持不同背镇,所以會有一個與版本相關(guān)的一個判斷。至于這個版本之間有什么不同可以參考總結(jié)說明中列出來的文件泽裳。

其實 generatelayout 就做了一件事瞒斩,那就是根據(jù) window 的各種屬性去獲取不同的xml文件。

總結(jié)

setContentView 執(zhí)行流程中主要涉及到3個類 PhoneWindow.java涮总,Activity.java 和 Window.java

Window 和 windowmanager 中的 各種feature 和 flag的style 對應(yīng)的各種含義以及動畫 style在\android\android\frameworks\base\core\res\res\values\attrs.xml 文件中有注釋說明

在 menu鍵 的設(shè)置中涉及到了版本問題胸囱,包括 3.0,4.0 和 5.0 分別有對應(yīng)的不同處理瀑梗,參考 \android\android\frameworks\base\core\java\android\os\Build.java 可以看到注釋有說明各版本有什么不同

至于為什么說 mDecor 是 最外層view烹笔,是因為在 generateLayout 方法中 mDecor 將填充該xml文件的 view一一mContentRoot 添加了進來。

Activity在啟動加載布局的操作

創(chuàng)建 DecorView 的布局:setContentView 的流程基本是用來創(chuàng)建 DecorView 的布局

將布局添加到 window 窗口:在 Activity 的啟動過程中夺克,會將應(yīng)用窗口添加到 WindowManager 中進行統(tǒng)一管理箕宙,以及綁定 DecorView

對于狀態(tài)欄和導航欄,是在每次 window 屬性發(fā)生變化時會去更新铺纽,但是只是設(shè)置了一個背景色柬帕,只是占位用,沒有加載這些view


文章原創(chuàng)作者GuoLin 書籍推薦

郭林大神原創(chuàng)android 書籍:《第一行代碼 android》

淘寶鏈接:

https://s.click.taobao.com/t?e=m%3D2%26s%3DgKUfuKdAZKocQipKwQzePOeEDrYVVa64K7Vc7tFgwiHjf2vlNIV67p2n%2BQBNMyE6Rku8%2Bpj6eJall3bs%2B3NRhNHnsKI%2BqxhyM0iVZhTFBom4YIorMPnmg8G0g2OJi%2FzmXHfenomYtn5EW9vzeG8LzfPUwktUBEmkxg5p7bh%2BFbQ%3D&pvid=10_106.6.161.154_3367_1490163222155

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末狡门,一起剝皮案震驚了整個濱河市陷寝,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌其馏,老刑警劉巖凤跑,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異叛复,居然都是意外死亡仔引,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門褐奥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來咖耘,“玉大人,你說我怎么就攤上這事撬码《梗” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵呜笑,是天一觀的道長夫否。 經(jīng)常有香客問我彻犁,道長,這世上最難降的妖魔是什么凰慈? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任汞幢,我火速辦了婚禮,結(jié)果婚禮上溉瓶,老公的妹妹穿的比我還像新娘急鳄。我一直安慰自己,他們只是感情好堰酿,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布疾宏。 她就那樣靜靜地躺著,像睡著了一般触创。 火紅的嫁衣襯著肌膚如雪坎藐。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天哼绑,我揣著相機與錄音岩馍,去河邊找鬼。 笑死抖韩,一個胖子當著我的面吹牛蛀恩,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播茂浮,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼双谆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了席揽?” 一聲冷哼從身側(cè)響起顽馋,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎幌羞,沒想到半個月后寸谜,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡属桦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年熊痴,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片聂宾。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡愁拭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出亏吝,到底是詐尸還是另有隱情,我是刑警寧澤盏混,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布蔚鸥,位于F島的核電站惜论,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏止喷。R本人自食惡果不足惜馆类,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望弹谁。 院中可真熱鬧乾巧,春花似錦、人聲如沸预愤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽植康。三九已至旷太,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間销睁,已是汗流浹背供璧。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留冻记,地道東北人睡毒。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像冗栗,于是被迫代替她去往敵國和親演顾。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

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