LayoutInflater中inflate方法两个参数和三个参数的区别

1,671 阅读4分钟
inflate方法从大范围来看,分两种,三个参数的构造方法和两个参数的构造方法


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


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

那么他们的区别是什么? root 是否传值为 null 或者 attachToRoot 等于ture和false的区别,下面我们就来试一试

一 第一种构造方法

1 root不为null,attachToRoot为true


activity_main

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:id="@+id/ll"
    tools:context="org.sang.layoutinflater.MainActivity">
</LinearLayout>


linlayout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/ll"
    android:layout_width="200dp"
    android:layout_height="200dp"
    android:background="@color/colorPrimary"
    android:gravity="center"
    android:orientation="vertical">
 
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

把这个linlayout.xml布局文件添加到我的activity的布局中,那么我可以这么做:

 setContentView(R.layout.activity_main); 

 LinearLayout ll = (LinearLayout) findViewById(R.id.ll); 

 LayoutInflater inflater = LayoutInflater.from(this); 

 inflater.inflate(R.layout.linearlayout, ll,true); 


小伙伴们注意到,这里我都没写将inflate出来的View添加到ll中的代码,但是linearlayout布局文件就已经添加进来了,这就是因为我第三个参数设置为了true,表示将第一个参数所指定的布局添加到第二个参数的View中。最终显示效果如下:



如果此时我们再加上一句,就会抛出以下异常,因为这个view早已被添加进来了,再次添加就会抛出异常

 ll.addView(view)

java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.


root不为null,attachToRoot为false

setContentView(R.layout.activity_main);

LinearLayout ll = (LinearLayout) findViewById(R.id.ll);

LayoutInflater inflater = LayoutInflater.from(this);

inflater.inflate(R.layout.linearlayout, ll,false); 

 ll.addView(view)


如果root不为null,而attachToRoot为false的话,表示不将第一个参数所指定的View添加到root中,那么这个时候有的小伙伴可能就有疑问了,既然不添加到root中,那我还写这么多干嘛?我第二个参数直接给null不就可以了?其实不然,这里涉及到另外一个问题:我们在开发的过程中给控件所指定的layout_width和layout_height到底是什么意思?该属性的表示一个控件在容器中的大小,就是说这个控件必须在容器中,这个属性才有意义,否则无意义。这就意味着如果我直接将linearlayout加载进来而不给它指定一个父布局,则inflate布局的根节点的layout_width和layout_height属性将会失效(因为这个时候linearlayout将不处于任何容器中,那么它的根节点的宽高自然会失效)。如果我想让linearlayout的根节点有效,又不想让其处于某一个容器中,那我就可以设置root不为null,而attachToRoot为false。这样,指定root的目的也就很明确了,即root会协助linearlayout的根节点生成布局参数,只有这一个作用。OK,还是上面的布局文件,如果我想将之添加到activity的布局中又该如何呢? 



我们发现和第一种效果是一样的,因为我们手动 ll.addView(view) 把布局添加了进来,同时root不为空是又约束了 view 的宽高


3 root为null,attachToRoot为false

当root为null时,不论attachToRoot为true还是为false,显示效果都是一样的。当root为null表示我不需要将第一个参数所指定的布局添加到任何容器中,同时也表示没有任何容器来来协助第一个参数所指定布局的根节点生成布局参数。我还是使用上文提到的linearlayout,我们来看下面一段代码

 setContentView(R.layout.activity_main); 

LinearLayout ll = (LinearLayout) findViewById(R.id.ll); 

 LayoutInflater inflater = LayoutInflater.from(this); 

 View view = inflater.inflate(R.layout.linearlayout, null, false);  

ll.addView(view);



当第二个参数为null,第三个参数为false时(即使为true显示效果也是一样的,这里以false为例),由于在inflate方法中没有将linearlayout添加到某一个容器中,所以我需要手动添加,另外由于linearlayout并没有处于某一个容器中,所以它的根节点的宽高属性会失效

二 第二种构造方法

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)


当我们没有传递attachToRoot 时 默认为true

LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
LayoutInflater inflater = LayoutInflater.from(this);
inflater.inflate(R.layout.linlayout, ll);

效果如图