首页 > 代码库 > android LayoutInflater.inflate详解

android LayoutInflater.inflate详解

LayoutInflater概述

从XML文件中实例化一个布局成对应的View类, 它从来不会直接使用, 而是使用getLayoutInflater()或者getSystemService(String)来获得一个对应当前context的标准LayoutInflater 实例。

例如:    

1
2
3
LayoutInflater inflater = (LayoutInflater)context.getSystemService
 
      (Context.LAYOUT_INFLATER_SERVICE);

 

如果要在自己的views中通过LayoutInflater.Factory来创建LayoutInflater你可以用cloneInContext(Context)来克隆一个当前存在的ViewFactory然后再用setFactory(LayoutInfalter.FActory) 来设置成自己的FActory.

起因

原来在项目中一直习惯用inflater.inflate(R.layout.layout, null)最近却发现会有一个黄色的警告。 十分好奇,所以决定找出原因。

我们发现inflate方法有两个:

  • View inflate(int resource, ViewGroup root)

  • View inflate(int resource , ViewGroup root, boolean attachToRoot) 第二个参数是指实例的布局所要放入的根视图。
    一般我们在不需要将该布局放入根视图的时候都会把第二个参数传为null,这样系统就不会去进行相应的绑定操作了,不然就蹦了。 我相信很多人都会这样理解,所以都很少用到 第二个方法, 其实这样是错误的。

原因在于android:layout_xyz属性会在父视图中重新计算,而你用第一个方法是说需要被添加到父视图中,只不过你不知道添加到哪一个父视图中, 所以你在xml中定义的LayoutParams 就会被忽略(因为没有已知的父视图)。

示例

大家肯定遇到过在ListViewitem布局中设置的高度没有效果的问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<LinearLayout xmlns:android="
http://schemas.android.com/apk/res/android
"
 
    android:layout_width="match_parent"
 
    android:layout_height="100dip"
 
    android:gravity="center_vertical"
 
    android:orientation="horizontal">
 
    <TextView
 
        android:layout_width="wrap_content"
 
        android:layout_height="wrap_content"
 
        android:text="test" />
 
</LinearLayout>
1
2
3
4
5
6
7
8
9
10
11
public View getView(int position, View convertView, ViewGroup parent) {
 
    if (convertView == null) {
 
        convertView = inflate(R.layout.item_lv_test, null);
 
    }
 
    return convertView;
 
}

如果用上面的代码会发现设置100dp是无效的。

而如果换成下面的代码就可以了。

1
2
3
4
5
6
7
8
9
10
11
public View getView(int position, View convertView, ViewGroup parent) {
 
    if (convertView == null) {
 
        convertView = inflate(R.layout.item_lv_test, nullfalse);
 
    }
 
    return convertView;
 
}

这里你该会想一想为什么很多需要显示View的方法中都有ViewGroup这个参数。
所以有些人会说在跟布局中设置是无效的,要再嵌套一层布局。 这样是错误的,会造成布局层级增多,影响性能。

 

细节

  • setContentView()LayoutInfalter.inflate()的区别 setContentView()一旦调用,就会立即显示UI. 而LayoutInfalter.inflate()只是把布局转换成对应的View对象,不会立即显示,只有需要的时候再显示出来。

  • View.inflate()方法与LayoutInflater.inflate()的区别 直接上源码:

1
2
3
4
5
6
7
public static View inflate(Context context, int resource, ViewGroup root) {
 
    LayoutInflater factory = LayoutInflater.from(context);
 
    return factory.inflate(resource, root);
 
}

android LayoutInflater.inflate详解