參考一些網(wǎng)上的資料以及個(gè)人的理解來(lái)介紹 Android view的繪制流程
1.上圖是一個(gè)Activity窗口結(jié)構(gòu)圖
當(dāng)activity創(chuàng)建的同時(shí)也會(huì)關(guān)聯(lián)一個(gè)window放坏,Window即窗口域滥,窗口是一個(gè)宏觀的思想,它是屏幕上用于繪制各種UI元素及響應(yīng)用戶輸入事件的一個(gè)矩形區(qū)域黔姜。android.view.Window是一個(gè)抽象類。PhoneWindow這個(gè)類是Framework為我們提供的android.view.Window的具體實(shí)現(xiàn)分苇。我們平時(shí)調(diào)用setContentView()方法設(shè)置Activity的用戶界面時(shí)彤蔽,實(shí)際上就完成了對(duì)所關(guān)聯(lián)的PhoneWindow的ViewTree的設(shè)置。
2.setContentView()
這個(gè)方法只是完成了Activity的ContentView的填充挑社,而并沒有執(zhí)行View的繪制流程陨界。
3.ViewRoot
View的繪制是由ViewRoot來(lái)負(fù)責(zé)的。當(dāng)Activity啟動(dòng)時(shí)DecorView關(guān)聯(lián)了ViewRoot對(duì)象痛阻,這種關(guān)聯(lián)關(guān)系是由WindowManager來(lái)維護(hù)的菌瘪。
4.View繪制的起點(diǎn)
當(dāng)建立好了decorView與ViewRoot的關(guān)聯(lián)后,ViewRoot類的requestLayout()方法會(huì)被調(diào)用阱当,以完成應(yīng)用程序用戶界面的初次布局俏扩。實(shí)際被調(diào)用的是ViewRootImpl類的requestLayout()方法,這個(gè)方法的源碼如下:
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
// 檢查發(fā)起布局請(qǐng)求的線程是否為主線程
checkThread();
mLayoutRequested = true;
scheduleTraversals();
}
}
上面的方法中調(diào)用了scheduleTraversals()方法來(lái)調(diào)度一次完成的繪制流程弊添,該方法會(huì)向主線程發(fā)送一個(gè)“遍歷”消息录淡,最終會(huì)導(dǎo)致ViewRootImpl的performTraversals()方法被調(diào)用。下面油坝,我們以performTraversals()為起點(diǎn)嫉戚,來(lái)分析View的整個(gè)繪制流程。
三個(gè)階段
measure: 判斷是否需要重新計(jì)算View的大小免钻,需要的話則計(jì)算彼水;
layout: 判斷是否需要重新計(jì)算View的位置,需要的話則計(jì)算极舔;
draw: 判斷是否需要重新繪制View凤覆,需要的話則重繪制纪挎。
這三個(gè)子階段可以用下圖來(lái)描述: