先來解釋一下LayoutInflater這個名字,Inflater在英語的意思是打氣筒,直一點的翻譯就是 布局的打氣筒,發揮一下想象力,就是我們用一個特定的打氣筒,對代碼泵氣,一點一點地泵成我們看到的界面。
雖然很多人對它很陌生,但是其實我們經常使用到它,因為加載布局的任務通常都是在Activity中調用setContentView()方法來完成的,而setContentView()方法的內部也是使用LayoutInflater來加載布局的。
分析之前我們先要把打氣筒拿過來,一共有兩種方法:
1、LayoutInflater?layoutInflater?=?LayoutInflater.from(context);
2、LayoutInflater?layoutInflater?=?(LayoutInflater)?context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
然而,其實第一種只是第二種的封裝。我們可以看到這個“打氣筒”竟然是SystemService,系統服務,我們向系統借了個“打氣筒”啊。
有了“打氣筒”,就可以開始給代碼“打氣”了。(注,這里的代碼指的是xml布局文件)
泵氣前,需要解決兩個問題:給哪段代碼打氣,打完氣的界面放在哪里。于是,決定了這兩個問題的答案以后,我們開始打氣了:
layoutInflater.inflate(resourceId,?root);
inflate()方法一般接收兩個參數,第一個參數就是要加載的布局id,第二個參數是指給該布局的外部再嵌套一層父布局,如果不需要就直接傳null。這樣就成功成功創建了一個布局的實例,之后再將它添加到指定的位置就可以顯示出來了。
就是說,我們甚至可以先打氣,打好氣再決定成品的放置位置。
ok,現在我們再去看看這個打氣筒內部是如何工作的。我們準備用這個打氣筒給一個xml布局文件打氣:
以上三段代碼都非常簡單,任何Android基礎的都應該能看懂(看不懂的話說明你不應該看這篇文章)。定義了一個Activity的布局文件,作為父View,再定義了一個button的布局(button_layout。xml),用LayoutInflater將button的xml實例化為一個可用的view,再把這個view放置到之前的父View中。
拆開這個打氣筒之前,我們先來設想一下如果是有我們自己來實現這個打氣筒,我們該如何做。我們拿到手的xml,會包含很多的標簽,標簽和標簽間會相互嵌套。于是很多人幾乎脫口而出了:遞歸解析!于是我們開始構思:
先把這xml拿好,放在地上,從頭開始看,先把根View的屬性都那出來,根據根View的類型和屬性構建一個View,構建完成以后,我們再往下遍歷,遇到子標簽就把子標簽的整個內容扔回到這個方法,進行構建,如此遞歸到底,就把整個xml成功泵成一個View了。
拆開這個打氣筒,我們發現:不管你是使用的哪個inflate()方法的重載,最終都會輾轉調用到LayoutInflater的如下代碼中(部分調試輸出被刪除):
(我覺得文檔也挺有用的,所以也貼了上來)
(再次吐槽,簡書貼的代碼的排版很丑,所以只好截屏)
看完源碼,發現基本思路差不多。只是“子View遞歸”似乎不太一樣,是的,這里子View的“打氣”交給了rInflateChildren完成,而rInflateChildren指向的是rInflate方法。
(順便猜測一下,為什么和我們預期的遞歸不一樣呢,個人的想法的是:View和ViewGroup是不一樣的!雖然是廢話,但這就決定了root View的“打氣”跟子View的“打氣”是不一樣的)
代碼挺簡單的,就不過多解釋了,只是說一下的是,這段代碼由出現了Android的三個特殊標簽(RequestFocus、Include、Merge,還有一個是ViewStub也是特殊的標簽)。這個幾個標簽對UI布局優化非常重要,沒了解的朋友應該去了解一下。
OK,到這里,這個布局的“打氣筒”也差不多解釋到這里了,可以總結一下:
1、我們向系統申請借來了一個LayoutInflater,即布局的打氣筒;
2、我們給這個打氣筒接上需要被打氣的XML布局文件;
3、我們泵了第一下的氣,就把root View的模型泵脹了;
4、借著我們繼續用力,泵了幾下氣,root View中的第一個標簽也被泵脹了,如此泵下去,第一層嵌套的最深的view都被泵好了;
5、被泵好(注意泵好和泵脹的區別)的view就貼到上一層的父view上;
6、第5步的父view繼續泵它的下一個子view;
7、如此遞歸,第5步的父view的所有子view都泵好了,并把子view貼到這個父view上,這個父view宣布自己也被泵好了,也貼到了自己的父view上;
8、如此遞歸,所有的view(包括root view)都被泵好,泵氣結束;
Reference:http://blog.csdn.net/guolin_blog/article/details/12921889
寫在文尾:
1、本文是看了 郭霖 大牛的View解析系列(參看上文的Reference)以后,結合著源碼, 按著自己的理解寫的,如有錯漏或理解不當,煩請指出;
2、裝載請表明出處:http://www.lxweimin.com/p/e0f63741e77b#
3、本人廣州一大三軟件狗,請問有廣東地區的公司收Android實習生嗎,可掃地