1. 程式人生 > >View inflate方法和LayoutInflater inflate方法的區別詳解

View inflate方法和LayoutInflater inflate方法的區別詳解

我們在Android開發中,對於將佈局填充成View物件,最常用的兩種辦法是:View類的方法inflate和LayoutInflater類的inflate方法,

今天有朋友問到這兩種填充方法的區別,就查看了一下兩者的區別,寫成文章,以方便有需要的人。

首先我們要清楚兩者大致的區別,之後我們再來慢慢看兩者具體的不同之處

LayoutInflater類的inflate方法適用於所有需要進行佈局填充的場景,是Android中專門進行佈局填充的方法,Android中其他需要

使用佈局填充的地方,都會呼叫本方法,而不是View類中的inflate方法。該方法不是靜態方法,需要先建立LayoutInflater類的物件

才能呼叫。

View類中的inflate方法內部包裹了LayoutInflater類的inflate方法,這個方法是一個靜態方法,不需要建立View類的物件,直接使用

View類名呼叫,相比上一種方法是一種簡便方法。但很明顯,這個方法不如上一個方法功能強大。

若是您只想大概瞭解兩者的區別,您讀到這裡已經足夠了,下面的分析較為詳細,請根據您的需要閱讀下面的內容。

現在我們開始慢慢的研究兩者具體的不同之處。

因為LayoutInflater類的inflate方法是所有佈局填充方法的基石,我們先來看看這個方法吧。

我們從Google官方的SDK中的定義入手,得到比較標準的概念。

關於LayoutInflater類

該類是一個抽象類,繼承自Object,存在於android.view包下。接下來我們只看和本文相關的內容,

不會再做過多的擴充套件。

以下是SDK中的敘述:

Instantiates a layout XML file into its corresponding View objects. It is never used directly. Instead, use  or  to retrieve a standard LayoutInflater instance that is already hooked up to the current context and correctly configured for the device you are running on. For example:

1

LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

To create a new LayoutInflater with an additional  for your own views, you can use  to clone an existing ViewFactory, and then call  on it to include your Factory.

For performance reasons, view inflation relies heavily on pre-processing of XML files that is done at build time. Therefore, it is not currently possible to use LayoutInflater with an XmlPullParser over a plain XML file at runtime; it only works with an XmlPullParser returned from a compiled resource (R.something file.)

翻譯和闡述: 

LayoutInflater類的作用是,將xml佈局檔案例項化為它對應的View物件。這個類不能直接使用,也就是不能直接呼叫其中的成員。一般,我們通過getLayoutInflater()方法或者 

方法來獲得該類的例項,通過以上兩個方法獲得的LayoutInflater類例項,已經和當前的上下文關聯起來,並且已經正確配置在當前程式執行的裝置上。我們順便說一下這兩個獲得例項的方法:getLayoutInflater()方法,

並不是上下文的方法,Activity類有這個方法,不需要傳入引數,在Activity中直接呼叫即可。Fragment類也有這個方法,但是需要傳入一個Bundle物件作為引數。可以看到,通過該方法獲得的LayoutInflater類物件

和上下文環境相配合。getSystemService(String)方法是Context的方法,需要傳入Context的成員變數作為引數,獲得相應的物件,要獲得LayoutInflater物件,需要傳入Context.LAYOUT_INFLATER_SERVICE

以上介紹的LayoutInflater類是Android系統為我們提供的通用類,如果我們想要為我們的View物件建立專用的LayoutInflater類,則可以用到 ,這是一個LayoutInflater類內部的介面,通過

工廠包括進來。在這裡我大概說明一下這段話的意思和作用:當我在一個上下文環境中建立好了一個LayoutInflater工廠之後,我們又想在另一個上下文環境中使用這個LayoutInflater工廠,那該怎麼辦?這裡說的一種方法

其中的引數就是我們目前建立的LayoutInflater工廠。這樣建立完成後,我們在新上下文環境中,就可以呼叫目前上下文環境中綁定了LayoutInflater工廠的LayoutInflater類物件了。關於這裡的更詳細用法在本文中就不更多闡述了,有興趣的朋友請參看我的另一篇文章。

xml檔案在建立階段的前處理過程嚴重影響View物件填充階段的效能(進而影響整體軟體的效能),這是因為inflate方法內部使用的pull解析,若是xml檔案在進行填充之前已經被xml解析了,那麼inflate方法在使用時就非常輕鬆,否則會非常困難。因此,我們不會使用LayoutInflater類處理普通的xml檔案,而是用來處理已經編譯的xml檔案,例如R.··········,這樣的xml檔案會返回一個已經解析了xml檔案的pull解析器,而普通的xml檔案返回的解析器則不然。更詳細的內容請參看我的另一篇文章。

好啦,通過以上介紹,我們大概對LayoutInflater類有了一個大概瞭解,之後我們來看以下這個類中的4個過載的inflate方法應該如何使用。

這4個方法中,有兩個是通過XmlPullParser作為資料來源建立view物件,剩下兩個就是我們平時常用的兩個通過resource目錄下的檔案作為資料來源的方法。

前兩個方法在此我們不做詳細介紹,這兩個方法我們平時工作根本不會用,但是Android原始檔中則大量使用,後邊我們詳細介紹的方法內部就是用前兩種實現的。今後我會在其他文章中細細的分析這兩個方法的使用,希望能幫助到感興趣的朋友。

接下來我們就看看下邊兩個常用方法的使用。

三個引數的方法

public View inflate (int resource, ViewGroup root, boolean attachToRoot)

Inflate a new view hierarchy from the specified xml resource. Throws  if there is an error.

從指定的xml檔案生成新的view檢視關係。出現錯誤時,丟擲InflateException異常。

引數分析

第一個引數,就是我們要填充的xml檔案

第二個引數,這個要和第三個引數有關係,大家慢慢看。若是第三個引數為true,那麼第二個引數的意義是,從第一個引數填充成的view物件的父控制元件;若是第三個引數為false,那麼第二個引數的意義是,

可以為第一個引數生成的view物件的根佈局提供一系LayoutParams引數的控制元件。

第三個引數,從第一個引數填充成的view物件是否要附著到第二個引數指定的空間上作為子控制元件。

說明:第一個引數不需多說,我們一般就從resource目錄下找到我們要填充的佈局檔案即可,切不可用普通的xml檔案進行填充,除非我們自己做好了相應的xmlpullparser。

若第二個引數為null,也就是我們不指定父控制元件,那麼新生產的view物件的根佈局的某些引數會失效,比如Layout_width和Layout_height會失效,這個大家可以做實驗嘗試,無論第三個引數是什麼。

關於該方法的使用只介紹到這裡,更詳細的用法請查詢專門講解該方法的文章。

返回:若提供了root,且第三個引數為true,則返回root作為根佈局,否則,返回填充出的view物件的根佈局作為根佈局。

兩個引數的用法

public View inflate (int resource, ViewGroup root)

從指定的xml檔案生成新的view檢視關係。出現錯誤時,丟擲InflateException異常。

引數分析:

第一個引數,要填充的xml檔案。

第二個引數,生成的view物件的父控制元件。同樣該引數可以為null。若提供了root,則返回root作為根佈局,否則,返回填充出的view物件的根佈局作為根佈局。

該方法內部呼叫了三個引數的方法,請看下面原始碼:

1

2

3

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {

return inflate(resource, root, root != null);

}

兩個引數方法的使用完全和三個引數方法相對應,在此不做更多介紹。

關於View類的inflate方法

public static View inflate (Context context, int resource, ViewGroup root)

Inflate a view from an XML resource. This convenience method wraps the  class, which provides a full range of options for view inflation.

 將一個xml資源填充成一個view物件。這個簡便的方法包裹了LayoutInflater類,後者提供了view物件填充的所有方法。

引數分析:

第一個引數,上下文

第二個引數,要填充的xml資源

第三個引數,填充成的view物件的根佈局

說明,從SDK解釋中的“convenience”一詞中,我們就可以看到View類中inflate的主要特點,就是簡便。它將LayoutInflater類封裝,且是一個靜態方法,便於呼叫。

以下為原始碼:

1

2

3

4

public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {

LayoutInflater factory = LayoutInflater.from(context);

return factory.inflate(resource, root);

}

可以看到其內部也就是呼叫了LayoutInflater兩個引數的inflate方法而已,已經在上面介紹過了,不再贅述。

好啦,那我們總結一下吧:  

LayoutInflater類的inflate方法適用於所有需要進行佈局填充的場景,是Android中專門進行佈局填充的方法,Android中其他需要

使用佈局填充的地方,都會呼叫本方法,而不是View類中的inflate方法。該方法不是靜態方法,需要先建立LayoutInflater類的物件

才能呼叫。

View類中的inflate方法內部包裹了LayoutInflater類的inflate方法,這個方法是一個靜態方法,不需要建立View類的物件,直接使用

View類名呼叫,相比上一種方法是一種簡便方法。但很明顯,這個方法不如上一個方法功能強大。