setContentView是如何一步一步被顯示出來的?

鍾離四郎發表於2018-07-26

通常我們在onCreate中會呼叫setContentView方法,如下:

image.png
setContentView裡面優勢怎麼樣執行的呢,進去看看,如下:
image.png

跳轉到getWindow().setContentView(layoutResID)如下:

image.png

Window型別的繼承樹如下:

image.png
Window只有一個實現類PhoneWindow,那也就是說getWindow().setContentView(layoutResID)呼叫的是PhoneWindow的setContentView,如下:
image.png
先來看看上圖中標記A的地方,呼叫installDecor方法,看名字的意思是建立decor的意思,而這個decor如果你熟悉Adroid 檢視的層級結構的話,會一下子就理解,這裡我給一張圖幫助你理解:
無標題.png

DecorView實際上是作為Activity上的檢視的最頂層View,而我們自己的佈局則是上圖粉色區域,外面還包含著一層,稱之為contentParent,從名字上看也是取得很貼切,嗯還是進入原始碼看看一下是不是上圖描述的那樣,如下:

image.png
genereteDecor方法呼叫如下:
image.png
generateLayout方法如下:
image.png

至此可以看到最頂層佈局,以及我們自己的佈局的復佈局都已建立好了,回到上圖示記B 的地方,可以看到呼叫了 mLayoutInflater.inflate(layoutResID, mContentParent); 這個layoutResID就是我們自己的佈局的id,呼叫完這一句我們自己的佈局也被建立出來了,到這裡你應該會有一個疑問:Activity的整個View檢視都被建立好了,那麼接下來應該是要繪製這個檢視才對,我第一次看這個原始碼的時候也是有這個疑問,同時還犯了一個錯誤,我試圖在mLayoutInflater.inflate(layoutResID, mContentParent);這句之後查詢開啟繪製試圖的程式碼,檢視原始碼我根本就找不到,一下子就懵逼了,如下:

image.png

其實這是我忽略了一個事實,這個setCotentView 是在onCreate被呼叫的這個時候View是不能見,真正能見的是在onResum時候,對哦,恍然大悟!!如果你有閱讀之前的那篇Activity生命週期回撥是如何被回撥的?應該會知道onResume何時開始被呼叫,如下:

image.png
image.png
上圖這個方法是在ActivityThread類中的,看到標記E的地方,是開始Activity的onResume的呼叫,進去看看,如下:

image.png

進入wm.addView看看如何,呼叫的是它的實現類WindowManagerImpl的addView如下:

image.png
跳轉如下:
image.png
ViewRootImpl呼叫setView如下:
image.png
setView方法裡面呼叫了requestLayout,這個方法名讓我們看到了是在做繪製View檢視的苗頭,進去看看是不是如此:
image.png
image.png
mTraversalRunnable物件的類相貌如下:

image.png
可以看到在run方法裡面呼叫doTraversal,如下:
image.png

performTraversals方法的程式碼是在是太長了,這裡我不截圖,這個方法裡面呼叫了三個關鍵的方法:performMeasure方法開啟檢視的測量流程,performLayout方法開啟了檢視的佈局流程,performDraw開啟了檢視的繪製流程,這3個方面的具體細節我準備在其他篇章來介紹,這3個流程走完,檢視就會被真正的繪製完成。到此setContentView的工作是如何一步一步被現實的,你是否有一個比較深的理解了,回顧一下前面講的東西,可以總結如下:

1.setContentView只是將Activity的整個View檢視建立好,放在一邊而已,而執行建立View檢視的則是PhoneWindow

2.在Activity在準備轉換成Resume狀態的之際,即呼叫handleResumeActivity,會將最頂層View——DecorView兜兜轉轉傳到WindowManagerGlobal 手中

3.DecorView在WindowManagerGlobal 手中,首先先新增進View陣列方便管理同時會為這個DecorView也可以說是這個檢視建立一個ViewRootImpl

4.ViewRootImpl 將呼叫setView 將DecorView傳入,開啟繪製之旅

相關文章