天天看點

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

轉載來自:http://www.cnblogs.com/baipengzhan/p/6257510.html

我們在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 getLayoutInflater() or getSystemService(String) 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 LayoutInflater.Factory for your own views, you can use cloneInContext(Context) to clone an existing ViewFactory, and then call setFactory(LayoutInflater.Factory) 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()方法或者 getSystemService(String)

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

并不是上下文的方法,Activity類有這個方法,不需要傳入參數,在Activity中直接調用即可。Fragment類也有這個方法,但是需要傳入一個Bundle對象作為參數。可以看到,通過該方法獲得的LayoutInflater類對象

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

以上介紹的LayoutInflater類是Android系統為我們提供的通用類,如果我們想要為我們的View對象建立專用的LayoutInflater類,則可以用到LayoutInflater.Factory ,這是一個LayoutInflater類内部的接口,通過

工廠設計模式可以使我們獲得定制的專用LayoutInflater類。我們可以使用cloneInContext(Context)來克隆一個已經存在的ViewFactory,然後調用setFactory(LayoutInflater.Factory)方法,将我們建立好的

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

是,我們在目前上下文環境中,使用LayoutInflater類對象調用cloneInContext(Context)方法,其中的參數填寫新上下文對象,因為我們要在新的上下文環境中使用。然後接着調用setFactory(LayoutInflater.Factory)方法,

其中的參數就是我們目前建立的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 InflateException 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 LayoutInflater 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類名調用,相比上一種方法是一種簡便方法。但很明顯,這個方法不如上一個方法功能強大。