View inflate方法和LayoutInflater inflate方法的区别详解

时间:2023-01-23 20:13:15

原创文章,转载请注明出处: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:

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对象的根布局作为根布局。

该方法内部调用了三个参数的方法,请看下面源码:

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类封装,且是一个静态方法,便于调用。

以下为源码:

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类名调用,相比上一种方法是一种简便方法。但很明显,这个方法不如上一个方法功能强大。