Android點(diǎn)五

一耙饰、View繪制流程

Android繪制流程詳盡版
AndroidView繪制精簡(jiǎn)版
ViewRootImpl和繪制流程
Android View繪制流程

主流程

ViewRootImpl 是連接 WindowManager 和 DecorView 的紐帶舍败,測(cè)量、放置和繪制三大流程都是通過(guò) ViewRootImpl 實(shí)現(xiàn)的。
在 ActivityThread 的 handleResumeActivity() 方法中纸型,會(huì)調(diào)用 WindowManager 的 addView() 方法蘸泻,而具體添加 DecorView 的操作是在 WindowManagerGlobal 中。(WindowManager是個(gè)接口)
在 WindowManagerGlobal 的 addView() 方法中脱篙,會(huì)把 DecorView 添加到 Window 中娇钱,同時(shí)會(huì)創(chuàng)建 ViewRootImpl ,并調(diào)用 ViewRootImpl 的 setView() 方法 把 ViewRootImpl 和 DecorView 關(guān)聯(lián)起來(lái)绊困。
View 的繪制流程是從 ViewRootImpl 的 performTraversals() 方法開(kāi)始的文搂,它經(jīng)過(guò)測(cè)量(measure)、放置(layout)和繪制(draw)三個(gè)過(guò)程才能把一個(gè) View 繪制出來(lái)秤朗,measure() 方法用于測(cè)量 View 的寬高煤蹭,layout() 用于確定 View 在父容器中的放置位置,draw() 負(fù)責(zé)做具體的繪制操作川梅。

ViewRootImpl

要討論View的繪制流程疯兼,必須要知道一個(gè)類(lèi)ViewRootImpl.
ViewRootImpl是連接WindowManager和DecorView的紐帶。繪制流程中的測(cè)量(measure)贫途、布局(layout)和繪制(draw)都是通過(guò)ViewRootImpl實(shí)現(xiàn)的吧彪。
ViewRootImpl創(chuàng)建過(guò)程

ActivityThread # handleResumeActivity中調(diào)用WindowManager # addView,而WindowManager只是繼承ViewManager的一個(gè)接口丢早,其實(shí)現(xiàn)在WindowManagerImpl中姨裸。


image.png

WindowManagerImpl # addView中調(diào)用WindowManagerGlobal # addView秧倾。其內(nèi)部初始化了ViewRootImpl,并通過(guò)ViewRootImpl # setView()方法將view和ViewRootImpl關(guān)聯(lián)起來(lái)。


image.png

在decorView與ViewRootImpl建立關(guān)聯(lián)后傀缩,ViewRootImpl類(lèi)的requestLayout方法會(huì)被調(diào)用(上面的setView中調(diào)用)那先。
image.png

調(diào)用scheduleTraversals方法來(lái)調(diào)度一次完整的繪制流程,方法內(nèi)部通過(guò)內(nèi)存屏障保證繪制View的優(yōu)先級(jí)最高赡艰。

具體Api調(diào)用

ActivityThread:handleResumeActivity(該方法內(nèi)使用Context.getWindowManager創(chuàng)建WindowManager對(duì)象)→
WindowManager:addView(該方法內(nèi)WindowManager委托代理給一個(gè)WindowManagerGLobal對(duì)象)→
WindowManagerGLobal:addView(該方法內(nèi)創(chuàng)建了ViewRootImpl對(duì)象)→
ViewRootImpl:setView→requestLayout→scheduleTraversals→doTraversal→performTraversals(最終到達(dá)繪制的入口)
其中從WindowManager.addView開(kāi)始就是Activity創(chuàng)建Window的過(guò)程售淡,最終在ViewRootImpl對(duì)象的performTraversals中完成View的繪制(一個(gè)Window對(duì)象對(duì)應(yīng)了一個(gè)ViewViewRootImpl對(duì)象也對(duì)應(yīng)了一個(gè)View對(duì)象,即DecorView)
performTraversals()是繪制的入口慷垮,它依次調(diào)用performMeasure()揖闸、performLayout()和performDraw()三個(gè)方法,三個(gè)方法內(nèi)部分別調(diào)用了DecorView的measure()料身、layout()和draw方法汤纸。

其他:

其它相關(guān)問(wèn)題

1.getWidth()和getMeasuredWidth()的區(qū)別

getMeasuredWidth()、getMeasuredHeight()必須在onMeasure之后使用才有效)

getMeasuredWidth() 的取值最終來(lái)源于 setMeasuredDimension() 方法調(diào)用時(shí)傳遞的參數(shù)芹血;

getWidth()與getHeight()方法必須在layout(int l, int t, int r, int b)執(zhí)行之后才有效

getWidth()返回的是贮泞,mRight - mLeft,mRight幔烛、mLeft 變量分別表示 View 相對(duì)父容器的左右邊緣位置啃擦;

2.View.post(runnable)原理

利用Handler通信機(jī)制,發(fā)送一個(gè)Runnable到MessageQueue中说贝,當(dāng)View布局處理完成時(shí)议惰,自動(dòng)發(fā)送消息,通知UI進(jìn)程乡恕。借此機(jī)制言询,巧妙獲取View的高寬屬性,代碼簡(jiǎn)潔傲宜,相比ViewTreeObserver監(jiān)聽(tīng)處理运杭,還不需要手動(dòng)移除觀察者監(jiān)聽(tīng)事件。

3.requestLayout()的作用

requestLayout()也可以達(dá)到重繪view的目的函卒,但是與invalidate和postInvalidate不同辆憔,它會(huì)先調(diào)用onLayout()重新排版,再調(diào)用ondraw()方法报嵌。

當(dāng)view確定自身已經(jīng)不再適合現(xiàn)有的區(qū)域時(shí)虱咧,該view本身調(diào)用這個(gè)方法要求parent view(父類(lèi)的視圖)重新調(diào)用他的onMeasure、onLayout來(lái)重新設(shè)置自己位置锚国。特別是當(dāng)view的LayoutParams發(fā)生改變腕巡,并且它的值還沒(méi)能應(yīng)用到view上時(shí),這時(shí)候適合調(diào)用這個(gè)方法requestLayout()

4.Window&View

Window&View
①.window是什么血筑?
是所有Viewde直接管理者绘沉,任何視圖都通過(guò)window呈現(xiàn)煎楣。Activity的setContentView底層都通過(guò)Window完成。
-window是一個(gè)抽象類(lèi)车伞,唯一實(shí)現(xiàn)類(lèi)是PhoneWindow择懂;Window并不是實(shí)際存在的,而是以View的形式存在另玖。
-創(chuàng)建Window需要通過(guò)WindowManager創(chuàng)建
-實(shí)際使用中無(wú)法直接訪問(wèn)Window困曙,必須通過(guò)WindowManager
-Window具體實(shí)現(xiàn)位于WindowManagerService中,WindowManager和WindowManagerService的交互是通過(guò)IPC完成(PC是Inter-Process Communication的縮寫(xiě)日矫,含義為進(jìn)程間通信或者跨進(jìn)程通信赂弓,是指兩個(gè)進(jìn)程之間進(jìn)行數(shù)據(jù)交換的過(guò)程,這里指的是Binder)
-Window和View通過(guò)ViewRootImpl建立聯(lián)系
-WMS把所有的用戶(hù)消息發(fā)給View/ViewGroup,但是在View/ViewGroup處理消息的過(guò)程中哪轿,有一些操作是公共的, Window把這些公共行為抽象出來(lái), 這就是Window。

②.Window類(lèi)型
FrameWork定義了三種窗口類(lèi)型翔怎,三種類(lèi)型定義在WindowManager,通過(guò)LayoutParams.type設(shè)置窃诉。
-應(yīng)用窗口,對(duì)應(yīng)一個(gè)Activity赤套,每個(gè)Activity都包含一個(gè)Window對(duì)象飘痛。加載Activity由AmS完成,創(chuàng)建一個(gè)應(yīng)用窗口只能在Activity內(nèi)部完成(層級(jí)1~99)容握。
-子窗口宣脉,必須依附于任何類(lèi)型的父窗口(層級(jí)1000~1999)。
-系統(tǒng)窗口剔氏,不需要對(duì)應(yīng)任何Activity塑猖,如:狀態(tài)欄,導(dǎo)航欄,普通應(yīng)用程序不能創(chuàng)建系統(tǒng)窗口谈跛,必須要有系統(tǒng)應(yīng)用權(quán)限.(層級(jí)2000~2999)羊苟。
int值越大層位置越靠上
如下圖:

image.png

image.png

3.WindowManger的功能
主要就三個(gè):添加、更改感憾、刪除View


image.png

WindowManger是一個(gè)接口蜡励,ViewManager是其父接口,WindowMangerImpl是其實(shí)現(xiàn)類(lèi)阻桅。

4.Activity的setContentView流程
Activity#setContentView()實(shí)際通過(guò)getWindow().setContentView()交由PhoneWindow處理凉倚。
PhoneWindow中主要做兩件事:
①當(dāng)mDecor為空的時(shí)候,通過(guò)installDecor()初始化DecorView(mDecor)【DecoreView本質(zhì)就是一個(gè)FrameLayout嫂沉,是Activity中的頂級(jí)View】
②generateLayout()實(shí)際就是獲取布局的父容器(mContentParent), 然后通過(guò)inflate將我們的setContentView傳入的View或者layout布局文件填充到這個(gè)mContentParent稽寒,而這個(gè)父容器mContentParent實(shí)際上就是DecorView的id為R.id.content的子容器。

5.Activity输瓜、Window瓦胎、DecorView芬萍、View之間的關(guān)系


image.png

DecorView 把屏幕劃分為了兩個(gè)區(qū)域:一個(gè)是 TitleView,也就是ActionBar或者TitleBar,一個(gè)是 ContentView搔啊,而我們平時(shí)在 Xml 文件中寫(xiě)的布局正好是展示在 ContentView 中柬祠。
6.DecorView何時(shí)被WindowManager添加到Window中?
ActivityThread的handleResumeActivity方法中负芋,首先會(huì)調(diào)用Activity的onResume方法漫蛔,接著調(diào)用Activity的makeVisible()方法
makeVisible()中通過(guò)WindowManager.addView()完成了DecorView的添加和顯示兩個(gè)過(guò)程


image.png

7.Dialog的創(chuàng)建過(guò)程:
//TODO

8.Window常見(jiàn)FLAG屬性


image.png

image.png

這些屬性有幾個(gè)還有很重要的,比如:
FLAG_KEEP_SCREEN_ON: 屏幕常亮旧蛾,可以在播放視頻的時(shí)候設(shè)置這個(gè)參數(shù)
FLAG_FULLSCREEN: 沉浸式全屏
FLAG_SECURE:禁止截屏
FLAG_SHOW_WHEN_LOCKED:窗口在鎖屏窗口上顯示

Android事件分發(fā)機(jī)制
https://cloud.tencent.com/developer/article/1601306

Android問(wèn)題簡(jiǎn)單匯總

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末莽龟,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子锨天,更是在濱河造成了極大的恐慌毯盈,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件病袄,死亡現(xiàn)場(chǎng)離奇詭異搂赋,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)益缠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén)脑奠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人幅慌,你說(shuō)我怎么就攤上這事宋欺。” “怎么了胰伍?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵齿诞,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我喇辽,道長(zhǎng)掌挚,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任菩咨,我火速辦了婚禮吠式,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘抽米。我一直安慰自己特占,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布云茸。 她就那樣靜靜地躺著是目,像睡著了一般。 火紅的嫁衣襯著肌膚如雪标捺。 梳的紋絲不亂的頭發(fā)上懊纳,一...
    開(kāi)封第一講書(shū)人閱讀 49,185評(píng)論 1 284
  • 那天揉抵,我揣著相機(jī)與錄音,去河邊找鬼嗤疯。 笑死冤今,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的茂缚。 我是一名探鬼主播戏罢,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼脚囊!你這毒婦竟也來(lái)了龟糕?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤悔耘,失蹤者是張志新(化名)和其女友劉穎讲岁,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體衬以,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡催首,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了泄鹏。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡秧耗,死狀恐怖备籽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情分井,我是刑警寧澤车猬,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站尺锚,受9級(jí)特大地震影響珠闰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜瘫辩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一伏嗜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧伐厌,春花似錦承绸、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至卷扮,卻和暖如春荡澎,著一層夾襖步出監(jiān)牢的瞬間均践,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工摩幔, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留彤委,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓热鞍,卻偏偏與公主長(zhǎng)得像葫慎,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子薇宠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

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