view繪制流程

簡(jiǎn)介:

本文主要針對(duì)view的繪制流程,結(jié)合源碼做一個(gè)總結(jié),這里我將盡量用通俗的語(yǔ)言來(lái)進(jìn)行表述(這里以linearlayout為例,其他布局以此類推)

setContentView()調(diào)用

setContentView() 只是創(chuàng)建了個(gè)DecorView()對(duì)象,將我們的布局加載到DecorView()里面

Activity啟動(dòng)流程:

performLaunchActivity()
=>onCreate()(反射)
=>handleResumeActivity()
=>performResumeActivity(...)(會(huì)調(diào)Activity的方法的onResume()方法)
=>.....
總結(jié):上述是Activity啟動(dòng)流程的啟動(dòng)流程,通俗點(diǎn)說(shuō)就是setcontentview()創(chuàng)建DecorView對(duì)象后,然后在ActivityThread類里再通過(guò)上述一系列方法的調(diào)用,將DecorView加載進(jìn)去,最終繪制view,省略號(hào)部分為主要的調(diào)用方法,這里單獨(dú)分出如下一部分進(jìn)行講解

上面省略號(hào)的位置

=>wm.addView(....) (把decorview加載到windowmanager里)
=>WindowManagerImpl.addView()
=>root.setView(...)
=>ViewRootImpl類中(以上流程通俗點(diǎn)說(shuō)就是講布局加載進(jìn)來(lái),為后續(xù)繪制做準(zhǔn)備)
=>requestLayout()
=>scheduleTraversals()
=>doTraversal()
=>performTraversals()(這里開始真正的繪制)
總結(jié):這里是將上一步生成的DecorView對(duì)象通過(guò)wm.addView(....)方法加載進(jìn)windowmanager中,然后最終一路往下調(diào),最終會(huì)調(diào)到performTraversals(),(書上以及網(wǎng)上大多數(shù)講解都是直接從這里開始講的,沒(méi)有說(shuō)具體調(diào)到這里的由來(lái)),從這里開始真正view的繪制

繪制方法

如下開始從performTraversals()開始講解,該方法會(huì)依次調(diào)用圖像繪制的方法,這里以linearlayout為例,逐步講解,為了便于理解,這里盡量以通俗的語(yǔ)言進(jìn)行講解,我會(huì)盡量少用代碼,我會(huì)提供一個(gè)思路,帶著這個(gè)思路自行去看代碼會(huì)比直接講代碼印象深刻。

1.performMeasure(...)

onMeasure()

首先來(lái)說(shuō)說(shuō)計(jì)算長(zhǎng)寬的基本思路:首先linearlayout會(huì)通過(guò)一層一層的遍歷去拿到子布局的長(zhǎng)寬,然后通過(guò)子孩子的長(zhǎng)寬,來(lái)計(jì)算自己的長(zhǎng)寬,最終算出自己所占的長(zhǎng)寬。注:這里要留意寬高模式對(duì)計(jì)算的影響,如if (useLargestChild && (heightMode == MeasureSpec.AT_MOST || heightMode == MeasureSpec.UNSPECIFIED)) {mTotalLength = Math.max(totalLength, totalLength + largestChildHeight +lp.topMargin + lp.bottomMargin .getNextLocationOffset(child)); }這一句就是當(dāng)子布局模式為AT_MOST或者UNSPECIFIED的時(shí)候,當(dāng)前父布局的大小就取所有子布局的最大值,依次類推,這里感興趣的小伙伴可以自行去看源碼,這里只是舉了個(gè)例子

2.performLayout(...)

繪制位置,對(duì)應(yīng)LinearLayout里面的orientation,循環(huán)子view,前提不是gone,調(diào)用child.layout(),擺放子布局

3.performDraw()

這里用到模板設(shè)計(jì)模式,這里會(huì)去依次調(diào)用
=>draw(...)
=>drawSoftware(...)
=>mView.draw(...)(View里)
最終在view的draw()里進(jìn)行繪制
=>drawBackground(...)(繪制背景)
=>onDraw(...)(繪制自己)
=>dispatchDraw(...)(繪制子view,不斷去繪制子view的draw)
.....
首先繪制自己的背景,然后再去遍歷子view,再去繪制子view
總結(jié):這里可以這樣理解:首先最外層父布局調(diào)用去繪制自己最外層,等繪制完后再去繪制里面的子布局,依次類推,最終全部繪制完畢

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容