Android LayoutInflater inflate() 圖示詳解
之前在動態載入一個佈局時用 View.inflate()
去載入,最後沒加載出來,換為 LayoutInflater.from(mContext).inflate()
之後載入成功。具體場景我沒記清了,但是我們可以通過了解這兩個方式載入佈局的方法來規避以後 使用可能出現的問題。
既然是由 LayoutInflater.from(mContext).inflate()
引出的問題那就從怎麼使用開始去一步一步深挖。
LayoutInflater.from(this).inflate()
有 4 個構造方法,前面三個構造方法最終都會呼叫最後一個構造方法 inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot)
進行佈局的解析。
它的四個構造方法如下:
第一個構造方法 public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) { return inflate(resource, root, root != null); } 第二個構造方法 public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) { // 真正實現的過程太長,這裡就不貼程式碼了,可自行去檢視原始碼 } 第三個構造方法 public View inflate(XmlPullParser parser, @Nullable ViewGroup root) { return inflate(parser, root, root != null); } 第四個構造方法 public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) { // 真正實現的過程太長,這裡就不貼程式碼了,可自行去檢視原始碼 }
我們常用的是第一個構造方法,但是第一個構造方法會呼叫第二個建構函式,所以我們 直接分析第二個構造方法。
它的構造方法引數介紹如下所示:
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) { }
引數解釋:
-
@param resource
佈局檔案id
(例如R.layout.main_page
) -
@param root
- 如果引數三
attachToRoot
為true
, 則引數二是作為引數一中佈局檔案的父控制元件 - 如果引數三
attachToRoot
為false
, 則引數二是作為提供一組LayoutParams
值的物件
- 如果引數三
-
@param attachToRoot
指定引數一的佈局View
物件是否要作為 第二個引數控制元件上作為子控制元件
返回值:
-
@return
若root
不為空,且第attachToRoot
為true
,則返回root
作為根佈局,否則,返回引數一view
物件的根佈局 作為根佈局
LayoutInflater.from(mContext).inflate() 小結
來源於文末 郭神 部落格參考
- 如果
root
為null
,attachToRoot
將失去作用,設定任何值都沒有意義,載入的佈局檔案最外層的所有layout
屬性會失效,由父佈局來重新指定.
例項驗證
圖一是 root
為 null
, attachToRoot=true
修改 R.layout.inflate_test_btn
的寬度為 300dp
的結果,很明顯沒修改成功。在測試過程中我修改了 attachToRoot=false
,結果還是不變。

圖一.png
圖二是修改了父佈局寬度為 300dp

圖二.png
驗證結果正確:由父佈局指定。
-
如果
root
不為null
,attachToRoot
不論是true
或false
,載入的佈局檔案最外層的所有layout
屬性都有效,唯一的不同是:-
attachToRoot
為true
時,會自動呼叫root.addView(view, params)
,最後返回root
;
-
例項驗證
resource
為 R.layout.inflate_test_btn
, attachToRoot
為 true
, root
為 contentLayout
,完整呼叫如: LayoutInflater.from(this).inflate(R.layout.inflate_test_btn, contentLayout, true);
這時候如果不處理,會崩潰:
The specified child already has a parent. You must call removeView() on the child's parent first.
通過列印 parent 得到如下資訊:
onCreate: parent---->android.widget.LinearLayout{ 4016a11 V.E...... ......I. 0,0-0,0 #7f0d007e app:id/root_layout}
原來還可以這樣檢視父佈局。。
根據提示我們只能先移除其它 子view
再新增
結合圖三以及崩潰日誌,可以證明會自動呼叫 root.addView(view, params)。

圖三.jpg
驗證結果正確:會自動呼叫 root.addView(view, params),最後返回 root。
-
attachToRoot
為false
時,會返回view
,需手動呼叫root.addView(view, params).
例項驗證
resource
為 R.layout.inflate_test_btn
, attachToRoot
為 false
, root
為 contentLayout
,完整呼叫如: LayoutInflater.from(this).inflate(R.layout.inflate_test_btn, contentLayout, false);
通過列印 parent 得到如下資訊:
onCreate: parent---->null 不會崩潰,可以正常新增, 而且父佈局中的子 view 都存在
圖四可以證明 root.addView()
是需要手動新增的.

圖四.png
驗證結果:需手動呼叫 root.addView(view, params)
- 在不設定
attachToRoot
引數的情況下,如果root
不為null
,attachToRoot
引數預設為true
.
例項驗證
resource
為 R.layout.inflate_test_btn
, attachToRoot
不設定或者是設定為 false
, root
為 contentLayout
,完整呼叫如:
LayoutInflater.from(this).inflate(R.layout.inflate_test_btn, contentLayout, false);
LayoutInflater.from(this).inflate(R.layout.inflate_test_btn, contentLayout,);
LayoutInflater.from(this).inflate(R.layout.inflate_test_btn,contentLayout); 會崩潰 LayoutInflater.from(this).inflate(R.layout.inflate_test_btn,contentLayout,false); 不會崩潰
驗證結果正確:如果 root 不為 null, attachToRoot 引數預設為 true.
關於 View 類的 inflate 方法
View.inflate
是對 LayoutInflater inflate
的進一步封裝,但是隻實現了 LayoutInflater inflate
兩個引數的構造方法,所以功能相對 LayoutInflater
會弱一些。我們可以通過原始碼直接看出二者的關係。
View.inflate
實現的原始碼如下:
引數介紹: context 表示上下文 resource 表示要填充的 `xml` 檔案 root 填充成的 `view` 物件的根佈局 public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) { LayoutInflater factory = LayoutInflater.from(context); return factory.inflate(resource, root); } 構造方法中呼叫 LayoutInflater.from(this).inflate 兩個引數 的 inflate public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) { return inflate(resource, root, root != null); }
參考
ofollow,noindex">Android LayoutInflater原理分析,帶你一步步深入瞭解View(一)