在我們熟悉的oncreate()方法之中,我們往往會用setContentView()方法來設(shè)置我們的布局勺拣,那當(dāng)中又是怎樣實現(xiàn)的呢奶赠?我們通過源碼一探究竟;
setContentView()點進去會走到Window這個抽象類當(dāng)中药有。
通過對類的描述可知window實現(xiàn)類為PhoneWindow车柠,在這個類中找到setContentView()方法
此時在這個類中主要做兩個事情:一個是installDecor,另一個是inflate塑猖。前者是初始化DecorView(根布局)竹祷,后者是將我們的布局加載到DecorView當(dāng)中。那么具體過程是怎樣實現(xiàn)的的呢羊苟?
首先我們來看一下installDecor()方法塑陵,
mDecor為decorview對象,decorview繼承FrameLayout蜡励,由此可知它也是一個ViewGroup令花。那么decorview承擔(dān)著怎樣的角色呢?其實凉倚,decorview是整個ViewTree的最頂層View兼都,主要負責(zé)裝載各種View和Activity布局。mDecor通過generateDecor()方法實例化稽寒。進入到generateDecor()方法之中扮碧。
回到installDecor()方法中,接下來往下看
mContentParent:
// mDecor itself, or a child of mDecor where the contents go.(它要么是mDecor本身杏糙,要么是mDecor的子類的內(nèi)容慎王。)
進入到generateLayout(mDecor)方法中;
generateLayout方法當(dāng)中宏侍,發(fā)現(xiàn)了在此處進行了大量的requestFeature的調(diào)用赖淤,也就是說,我們的requestFeature設(shè)置其實是在setContentView方法當(dāng)中就開始了谅河, 這也是為什么我們自己要去getWindow.requestFeature時必須在setContent之前的原因咱旱。在generateLayout方法當(dāng)中接著往下看
由以上代碼可以看出,該方法還是做了相當(dāng)多的工作的绷耍,首先根據(jù)設(shè)置的主題樣式來設(shè)置DecorView的風(fēng)格吐限,比如說有沒有titlebar之類的,接著為DecorView添加子View锨天,而這里的子View則是上面提到的mContentParent毯盈,如果上面設(shè)置了FEATURE_NO_ACTIONBAR剃毒,那么DecorView就只有mContentParent一個子View病袄,這也解釋了上面的疑問:mContentParent是DecorView本身或者是DecorView的一個子元素搂赋。我們可以通過前面提到的getWindow.requestFeature進行設(shè)置,這里就不在具體說明益缠。默認情況下加載的是screen_simple.xml布局脑奠。我們看看布局中有什么?
通過下面這幅圖就可以看出DecorView結(jié)構(gòu)關(guān)系:
然后我們再回到setContentView()方法中來看inflate方法就比較容易了幅慌,就是我們的布局通過mContentParent加載到decorview容器中宋欺。
通過這幅圖便可以更直觀的理解資源加載流程。
小結(jié):DecorView是頂級View胰伍,內(nèi)部有titlebar和contentParent兩個子元素齿诞,contentParent的id是content,而我們設(shè)置的main.xml布局則是contentParent里面的一個子元素骂租。在DecorView創(chuàng)建完畢后祷杈,通過setContentView方法中inflate(layoutResID, mContentParent);這里加載了我們設(shè)置的main.xml布局文件,并且設(shè)置mContentParent為main.xml的父布局渗饮。