我知道你們都很討厭讀別人寫的源碼分析,由於動不動就長篇大論,不講武德,這樣合適嗎,這樣不合適。因而,這是一篇不同的源碼分析,若是看完你還說不懂。年輕人,我勸你:java
普通的一個 Activity-setContentView(),你知道它內部作了什麼嗎?web
咱們先來看一下Activity-setContentView方法:windows
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
複製代碼
簡簡單單滴方法,內部調用了 getWindows.setContentView(xxx)api
等等,Windows
是什麼?markdown
Windows
表示一個窗口的概念,Android 中無論是Activity,dialog,仍是 Toast 它們的視圖都是附加在 Windows 上,所以能夠稱 windows 是View的直接管理者。而Windows也只有實現類,即PhoneWindows.ide
咱們接着去看 PhoneWindows
的 setContentView()svg
@Override
public void setContentView(int layoutResID) {
if (mContentParent == null) {
installDecor(); //關注點
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
}
mLayoutInflater.inflate(layoutResID, mContentParent);
}
複製代碼
簡簡單單,內部執行了一個判斷,而後調用 **installDecor() ** 方法。源碼分析
等等,mContenParent
是什麼?佈局
mContentParent 即放置咱們本身佈局的容器,你能夠理解爲,它是咱們的根容器,詳情看圖。this
咱們接着去看 **installDecor()**方法:
private void installDecor() {
...忽略掉
mDecor = generateDecor(-1); //關注點1
...忽略掉
if (mContentParent == null) {
//關注點2
mContentParent = generateLayout(mDecor);
}
...忽略掉一大段
}
複製代碼
這個方法內部很繁瑣,很臭很長,咱們須要關注這麼多嗎,不須要,因此直接先進入 generateDecor().
等等,mDecor
是什麼?
mDecor 是
windows
惟一視圖,也就是咱們mContentParent
的爸爸。簡稱 DecorView,是否是回憶起了點什麼。
咱們接着去看 generateDecor() 方法
protected DecorView generateDecor(int featureId) {
...忽略一大段
return new DecorView(context, featureId, this, getAttributes());
}
複製代碼
哇,這個方法愛了愛了,直接new了一個 DecorView
,其餘也沒啥,返回回去看 installDecor() 中的關注點2-generateLayout().
咱們進入 generateLayout() 方法:
protected ViewGroup generateLayout(DecorView decor) {
//1
TypedArray a = getWindowStyle();
if(xx)else if(xxx)
else {
layoutResource = R.layout.screen_simple;
}
//2
mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
..忽略掉一部分
//3
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
return contentParent;
}
複製代碼
等等,這個 R.layout.screen_simple
是甚?
哦,這就是咱們DecorView中加載的佈局啊,具體大圖以下。
如上圖所示,咱們的佈局最終會被添加到這個根佈局content中。
咱們接下來將上面的分析總體走一遍:
PhoneWindows
(windows的惟一實例)的 setContenView() ;PhoneWindows
的 setContentView() 內部會先判斷當前有沒有佈局容器 contentParent
,也即就是有沒有 DecorView
,若是沒有,執行 installDecor() 去初始化咱們的 DecorView
與contentParent
;DecorView
,若是沒有,先new一個出來,而後判斷有沒有 contentParent(承載咱們本身佈局的ViewGroup)
,沒有的話,就去根據當前主題,選擇一個佈局,並將其當作咱們的根佈局添加到 DecorView
中,再將其中的子view,即R.id.content這個view賦值給咱們的 contentParent
;contentParent
裏了;