android-LayoutInflater的inflate方法详解

android-----LayoutInflater的inflate方法详解

        前面在使用Fragment的时候,我们通常都要重写他的onCreateView方法,这个方法的方法的使用如下:

        public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
                  return inflater.inflate(R.layout.fragment1,container,false);
        }

        可以看到我们通常都是调用LayoutInflater的inflate方法来获得这个View的,但是传入的这些参数到底是干什么的呢?我们有必要去看看android源码是怎么实现的了:

        从android官方API中我们可以看到LayoutInflater共有四个inflate方法:

  android-LayoutInflater的inflate方法详解

        这四个方法最终都会调用public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot)这个方法,所以我们只需要看看这个方法源码就可以了:

        这个方法的前面大半部分是通过XmlPullParser进行xml解析并且对解析的结果进行各种判断的,不是本方法的重点,我们仅看重要部分:

                    View temp;
                    if (TAG_1995.equals(name)) {
                        temp = new BlinkLayout(mContext, attrs);
                    } else {
                        temp = createViewFromTag(root, name, attrs);
                    }

                    ViewGroup.LayoutParams params = null;

                    if (root != null) {
                        if (DEBUG) {
                            System.out.println("Creating params from root: " +
                                    root);
                        }
                        // Create layout params that match root, if supplied
                        params = root.generateLayoutParams(attrs);
                        if (!attachToRoot) {
                            // Set the layout params for temp if we are not
                            // attaching. (If we are, we use addView, below)
                            temp.setLayoutParams(params);
                        }
                    }

        第10行首先会判断是否存在父视图,如果存在的话,则在16行获得子视图的布局参数,这里的attrs是通过XmlPullParser解析到的子视图资源文件中的xml标签所对应的set集合,第17行通过判断attachToRoot如果是false的话,则只将temp(是一个声明为View的局部变量)设置为子视图;

        如果root非空,并且attachToRoot为true的话,则会将当前子视图添加到父视图中;

 if (root != null && attachToRoot) {
           root.addView(temp, params);
 }
        如果root为空或者attachToRoot为false的话,则直接返回我们创建的temp

 if (root == null || !attachToRoot) {
            result = temp;
 }

        下面通过实例来看看传入不同的参数的效果:

         定义parent.xml作为父视图:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fatherLinearLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#00ff00" >
    <TextView 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="这是父视图"/>
</LinearLayout>
        定义child.xml作为子视图:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#ffff00" >
    <TextView 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="这是子视图"/>
</LinearLayout>
       第一种方式:inflate(view,null)
public class LayoutInflaterActivity extends Activity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		View childView = getLayoutInflater().inflate(R.layout.child, null);
		setContentView(childView);
	}
}
        输出结果:

  android-LayoutInflater的inflate方法详解
        第二种方式:inflate(view,root)

public class LayoutInflaterActivity extends Activity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		ViewGroup parentView = (ViewGroup) getLayoutInflater().inflate(R.layout.parent, null);
		View childView = getLayoutInflater().inflate(R.layout.child, parentView);
		setContentView(childView);
	}
}

        输出结果:

  android-LayoutInflater的inflate方法详解
        这种方式的输出结果和inflate(view,root,true)是一致的;

        第三种方式:inflate(view,root,false)

public class LayoutInflaterActivity extends Activity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		ViewGroup parentView = (ViewGroup) getLayoutInflater().inflate(R.layout.parent, null);
		View childView = getLayoutInflater().inflate(R.layout.child, parentView,false);
		setContentView(childView);
	}
}
        输出结果:

  android-LayoutInflater的inflate方法详解
        可以看到这种方式和root==null的显示效果是一样的,这一点从源码中也能找到答案:

 if (root == null || !attachToRoot) {
         result = temp;
 }
        只要inflate(view,root,attachToRoot)中root为null或者attachToRoot为false有一个成立的话,最后都会只显示当前子视图,我们可以对上面Activity代码进行修改,手动将子视图添加到父视图中:

public class LayoutInflaterActivity extends Activity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		ViewGroup parentView = (ViewGroup) getLayoutInflater().inflate(R.layout.parent, null);
		View childView = getLayoutInflater().inflate(R.layout.child, null,false);
		parentView.addView(childView);
		setContentView(parentView);
	}
}
        输出结果:

 android-LayoutInflater的inflate方法详解

        注意这种方式和inflate()方式将子视图加入父视图显示的效果是不一样的;这种方式是以父视图为主,inflate方式是以子视图为主;