1. 作用

官方释义

Inflate a new view hierarchy from the specified xml resource

大概意思就是从给定的xml中加载view树。

2. 用法

2.1 四种重载

1. public View inflate(@LayoutRes int resource, @Nullable ViewGroup root);
2. public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot);
3. public View inflate(XmlPullParser parser, @Nullable ViewGroup root)
4. public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot);

对外暴露的有四种重载,但是另外两种需要自行传入XmlPullParser,也就是说需要自行解析xml dom,属于高端操作,一般使用较少。
其中,方法1也是使用了方法2,只不过在root非空的情况下,默认attachToRoot=true,故本文主要对方法2进行分析。

2.2 三个参数一个返回值

2.2.1 resource

resource顾名思义,资源,从给定的注解来看,要求为layout资源。故参数一般为R.layout.my_layout。

2.2.2 root

root顾名思义,根布局,这里的根布局可以为空。
当根部局为空时,attachToRoot不生效且生成的view树根节点的LayoutParams为空,即你在layout中定义的根部局的什么宽啊高啊内边距外边距相对位置等一切以layout_为前缀的属性都会失效。为什么呢?我们来看看LayoutParam的定义:

LayoutParams are used by views to tell their parents how they want to be laid out

意思是,LayoutParams是被用来告诉父布局他想要怎么被摆放的。
如果给定的root为空,那么加载出来的view就没有父布局,当然也没必要拥有LayoutParams了!

2.2.3 attachToRoot

attachToRoot,即是否要将创建的view树附加(连接)到给定的根布局下。

2.2.4 返回值View

当不附加到根部局下时,返回的为给定layout的根节点。
当附加到根部局下时,返回的为根部局。

2.3 使用案例

所谓实践出真知,下面来看一组栗子。
首先是一个根布局,我们叫他root_layout

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/fl_root"android:layout_width="300dp"android:layout_height="300dp"android:background="@android:color/holo_red_light"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Hello World!"android:layout_gravity="center" /></FrameLayout>

接着是一个我们想要加载的布局inflate_layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/ll_inflate_root"android:layout_width="200dp"android:layout_height="200dp"android:background="@android:color/holo_blue_light"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:text="im inflated" /></LinearLayout>

之后我们找个Activity简单实验一下,这里只给出了onCreate方法

    @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);Log.d(TAG, "onCreate");// activity content部分的根部局,实际上也是使用了LayoutInflater.inflate// 将布局加载到了contentParent下,感兴趣的可以看下PhoneWindow下的实现setContentView(R.layout.root_layout);FrameLayout rootView = findViewById(R.id.fl_root);  // 首先拿到root_layout的view树根// 之后我们对inflateView进行测试,对应下面三种情况View inflateView = LayoutInflater.from(this).inflate(R.layout.inflate_layout, rootView, true);
//      View inflateView = LayoutInflater.from(this).inflate(R.layout.inflate_layout, rootView, false);
//      View inflateView = LayoutInflater.from(this).inflate(R.layout.inflate_layout, rootView);ViewGroup.LayoutParams rootLayoutParams = rootView.getLayoutParams();ViewGroup.LayoutParams inflateLayoutParams = inflateView.getLayoutParams();Log.d(TAG, "rootView=" + rootView + " rootView LayoutParams - " + rootLayoutParams);Log.d(TAG, "inflateView=" + inflateView + "inflateView LayoutParams -" + inflateLayoutParams);}
2.3.1 根布局非空
2.3.3.1 attachToRoot=true
D/MainActivity: rootView=android.widget.FrameLayout{6f919a1 V.E...... ......ID 0,0-0,0 #7f07003c app:id/fl_root} rootView LayoutParams - android.widget.FrameLayout$LayoutParams@16527c6
D/MainActivity: inflateView=android.widget.FrameLayout{6f919a1 V.E...... ......ID 0,0-0,0 #7f07003c app:id/fl_root}inflateView LayoutParams -android.widget.FrameLayout$LayoutParams@16527c6

当attachToRoot为true时,返回的为root根节点。且将我们的inflate_layout解析出的view树连接到了给的root下。

2.3.3.1 attachToRoot=false
D/MainActivity: rootView=android.widget.FrameLayout{6f919a1 V.E...... ......ID 0,0-0,0 #7f07003c app:id/fl_root} rootView LayoutParams - android.widget.FrameLayout$LayoutParams@16527c6
D/MainActivity: inflateView=android.widget.LinearLayout{3547387 V.E...... ......ID 0,0-0,0 #7f07004f app:id/ll_inflate_root}inflateView LayoutParams -android.widget.FrameLayout$LayoutParams@79282b4

当attachToRoot为false时,返回的为inflate_layout的根view,且根据给定的rootView生成了自己的LayoutParam。但view并未被插入到给定根节点的view树中。

2.3.1 根布局为空
D/MainActivity: rootView=android.widget.FrameLayout{6f919a1 V.E...... ......ID 0,0-0,0 #7f07003c app:id/fl_root} rootView LayoutParams - android.widget.FrameLayout$LayoutParams@16527c6
D/MainActivity: inflateView=android.widget.LinearLayout{3547387 V.E...... ......ID 0,0-0,0 #7f07004f app:id/ll_inflate_root}inflateView LayoutParams -null

根部局为空时,也未将生成的view插入到view树中(也不知道要往哪插)。并且与之前不同的是,LayoutParams为空!

3. 源码解析

public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {synchronized (mConstructorArgs) {// .....if (TAG_MERGE.equals(name)) {// merge标签的解析// 必须要attach到根节点if (root == null || !attachToRoot) {throw new InflateException("<merge /> can be used only with a valid "+ "ViewGroup root and attachToRoot=true");}// 递归的将当前merge标签下的孩子连接到根节点上rInflate(parser, root, inflaterContext, attrs, false);} else {// 其他标签的解析, temp是当前解析的layout的根节点// Temp is the root view that was found in the xmlfinal View temp = createViewFromTag(root, name, inflaterContext, attrs);ViewGroup.LayoutParams params = null;// 根节点非空时if (root != null) {// Create layout params that match root, if supplied// 从解析出来的attr中获取宽高,创建layoutparamparams = root.generateLayoutParams(attrs);if (!attachToRoot) {// Set the layout params for temp if we are not// attaching. (If we are, we use addView, below)// 如果不attach到root下才进行设置,不然等到addView的时候再进行设置temp.setLayoutParams(params);}}// Inflate all children under temp against its context.// 递归的inflate当前解析布局根view下的孩子们rInflateChildren(parser, temp, attrs, true);// We are supposed to attach all the views we found (int temp)// to root. Do that now.// 如果root不为空且要添加到根布局下时使用addViewif (root != null && attachToRoot) {// 将temp插入到根节点的最后一个孩子的位置,并设置他的layoutParam为paramsroot.addView(temp, params);}// Decide whether to return the root that was passed in or the// top view found in xml.// 如果根为空或者不连接到根节点时返回的是解析的layout.xml的根节点// 否则返回的为rootif (root == null || !attachToRoot) {result = temp;}}// .....return result;}}
    /*** Adds a child view with the specified layout parameters.** <p><strong>Note:</strong> do not invoke this method from* {@link #draw(android.graphics.Canvas)}, {@link #onDraw(android.graphics.Canvas)},* {@link #dispatchDraw(android.graphics.Canvas)} or any related method.</p>** @param child the child view to add* @param index the position at which to add the child or -1 to add last* @param params the layout parameters to set on the child*/public void addView(View child, int index, LayoutParams params) {// .....addViewInner(child, index, params, false);}
    private void addViewInner(View child, int index, LayoutParams params,boolean preventRequestLayout) {// .....// 如果给定的params是空,则为其创建一个,这个具体的实现在各个父亲那,看他们想咋摆孩子if (!checkLayoutParams(params)) {params = generateLayoutParams(params);}if (preventRequestLayout) {// 设置布局时不进行requestLayout,即只设置参数不进行刷新,一般用在正在onLayout时child.mLayoutParams = params;} else {child.setLayoutParams(params);}// .....}

大概就是酱紫,简单来说就是有无root决定加载出来的孩子是否是健全(知不知道自己多大应该在哪儿)的孩子,是否attachToRoot就是这孩子是要跟着他爹还是要自己单飞。
最后推荐一篇讲LayoutParams讲的不错的博客自定义控件知识储备-LayoutParams的那些事

Android LayoutInflater.inflate详解相关推荐

  1. LayoutInflater.inflate()详解

    学习自定义View一段时间了,从开始的一窍不通到现在终于能写出点东西了,前面也写过几篇关于自定义view的博客,但是感觉这东西吧,一天不敲又忘记了,所以准备写一篇自定义View系列的博客,这也算是我这 ...

  2. android开发照相机啊,Android照相机开发详解(一)

    Android相机开发详解(一) Android相机开发详解(一) 请支持原创,尊重原创,转载请注明出处:http://blog.csdn.net/kangweijian(来自kangweijian的 ...

  3. Android相机开发详解(一)

    Android相机开发详解(一) 请支持原创,尊重原创,转载请注明出处:http://blog.csdn.net/kangweijian(来自kangweijian的csdn博客) Android相机 ...

  4. Android:Frament详解

    Android:Frament详解 Fragment是什么 Fragment运行 Fragment是什么 具备生命周期:依托Activity运行 Fragment运行 <?xml version ...

  5. android中getSystemService详解

    原文地址:android中getSystemService详解作者:邹斌 http://blog.sina.com.cn/s/blog_71d1e4fc0100o8qr.html http://blo ...

  6. 《Android游戏开发详解》——第1章,第1.6节函数(在Java中称为“方法”更好)...

    本节书摘来自异步社区<Android游戏开发详解>一书中的第1章,第1.6节函数(在Java中称为"方法"更好),作者 [美]Jonathan S. Harbour,更 ...

  7. JMessage Android 端开发详解

    JMessage Android 端开发详解 目前越来越多的应用会需要集成即时通讯功能,这里就为大家详细讲一下如何通过集成 JMessage 来为你的 App 增加即时通讯功能. 首先,一个最基础的 ...

  8. 《Java和Android开发实战详解》——2.5节良好的Java程序代码编写风格

    本节书摘来自异步社区<Java和Android开发实战详解>一书中的第2章,第2.5节良好的Java程序代码编写风格,作者 陈会安,更多章节内容可以访问云栖社区"异步社区&quo ...

  9. Android事件流程详解

    Android事件流程详解 网络上有不少博客讲述了android的事件分发机制和处理流程机制,但是看过千遍,总还是觉得有些迷迷糊糊,因此特地抽出一天事件来亲测下,向像我一样的广大入门程序员详细讲述an ...

最新文章

  1. mysql初体验学习笔记_MySQL数据库初体验
  2. pwmc语言调速程序_51单片机的直流电机PWM调速系统设计,正转反转,加减速,急停等,仿真和代码...
  3. Redis缓存雪崩、缓存穿透、热点Key
  4. 一行代码引来的安全漏洞,就让我们丢失了整个服务器的控制权
  5. oracle文件系统挂载点,挂载和取消挂载 Oracle Solaris 文件系统
  6. 颜色模型和颜色应用---小结
  7. matplotlib text 文字处理
  8. Myeclipse 使用JUnit 进行单元测试
  9. VS 2017 产品密钥
  10. 一天一工程总结系列-7.2
  11. 一文了解caffe框架
  12. 编程语言分类-编译型,解释型
  13. 终极搞定硬盘“A disk read error occured,Press Ctrl+Alt+Del to restart”报错的彻底解决方法...
  14. 【C++ set的基本操作】
  15. 21天学Python --- 打卡2:Regular Expression
  16. ImageJ 用户手册——第三部分(ImageJ扩展)
  17. alert弹出窗口,点击确认后关闭页面
  18. UIStoryboardSegue(多控制器)
  19. 2018.01.27 我懂你的知识焦虑
  20. 【JVM】垃圾回收算法与分代回收

热门文章

  1. @Autowired注解的实现原理
  2. 广东海洋大学全国计算机考试,广东海洋大学2018年3月计算机等级考试报名时间...
  3. jquery 点击事件点击元素添加class,兄弟节点移除class
  4. win11玩绝地求生频繁闪退如何解决?
  5. VR渲染延迟优化方法
  6. android web hook,webhook
  7. FileMaker 实时定位当前地址
  8. 聊聊前端跨域的爱恨情仇
  9. 临床医学专业计算机必须过几级,临床、金融、计算机电子信息,这些专业过去现在未来都是大热门...
  10. 微信小游戏开发实战教程14-闯关模式的实现