在开发中,我们经常需要使用到LayoutInflater,通过该对象的inflate()方法,将一个layout布局文件实例化为View对象。

关于LayoutInflater对象的获取,参考博文:
http://blog.csdn.net/ruancoder/article/details/51760942

今天主要对inflate()方法的使用和源码进行分析。

(1).inflate()方法的使用

在实际使用中,我们一般会用到inflate的以下两个重载方法。

方法一:

public View inflate(int resource, ViewGroup root) {}

方法二:

public View inflate(int resource, ViewGroup root, boolean attachToRoot) {}

其中方法一最为常见。
常见使用案例一:

View myView = LayoutInflater.from(context).inflate(R.layout.my_view, null);

将布局文件/res/layout/my_view.xml实例化为myView对象。

常见使用案例二:

ViewGroup viewRoot;
LayoutInflater.from(context).inflate(R.layout.my_view, viewRoot);

将布局文件/res/layout/my_view.xml实例化的View对象添加到viewRoot布局中。

那么方法一与方法二有什么区别呢?
进入方法一的源码,我们会发现内部调用的其实就是方法二,只是将方法二的第3个参数设为“root != null”。

public View inflate(int resource, ViewGroup root) {return inflate(resource, root, root != null);
}

方法二中的参数和返回值释义:
参数:
resource:需要实例化的布局资源id。
root:ViewGroup类型视图组对象
attachToRoot:是否将resource实例化后的View添加到参数root中。
返回值:
如果root为空,直接返回resource实例化后的View对象;
如果root不为空,attachToRoot为true,将resource实例化为view对象,忽略view的最外层视图在xml布局中定义的属性,将view添加到root中,并将root返回。
如果root不为空,attachToRoot为false,将resource实例化为view对象,为view的最外层视图设置其在xml布局中定义的属性,并将view对象返回。

(2).inflate()方法的源码分析
进入inflate()方法内部。

public View inflate(int resource, ViewGroup root, boolean attachToRoot) {final Resources res = getContext().getResources();// 根据layout resource id,获取该布局的XmlResourceParser对象final XmlResourceParser parser = res.getLayout(resource);try {return inflate(parser, root, attachToRoot);} finally {parser.close();}
}

从方法内部可以看到,LayoutInflater使用的是pull解析器来解析xml布局文件的。获取到布局resource的XmlResourceParser对象后,接着进入下一个方法。

public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {// ...// attrs是传入的布局layout在xml文件里面设置的属性集合final AttributeSet attrs = Xml.asAttributeSet(parser);// 将ViewGroup类型的参数root赋值给resultView result = root;// temp是传入的参数resource的根布局Viewfinal View temp = createViewFromTag(root, name, inflaterContext, attrs);ViewGroup.LayoutParams params = null;// 实例化temp视图内的所有子视图rInflateChildren(parser, temp, attrs, true);if (root != null) {// 根据attrs属性集,创建布局参数paramsparams = root.generateLayoutParams(attrs);// 如果temp不需要添加到root中,那么为temp设置布局参数paramsif (!attachToRoot) {temp.setLayoutParams(params);}}if (root != null && attachToRoot) {// 将temp添加到root中,并使用布局参数paramsroot.addView(temp, params);}if (root == null || !attachToRoot) {// 将temp赋值给result(在此之前,result==root)result = temp;}// ...return result;
}

该方法是inflate()的关键,这里只抽取了需要关注的核心代码。

最开始,定义方法的返回值result,将参数root赋值给result,实例化参数resource赋值给temp。
接下来进入判断条件。
当root!=null时,根据resource的最外层view在xml中定义的的属性,创建布局参数params。如果!attachToRoot,为temp设置布局参数params。
当root!=null&&attachToRoot,将temp添加到root中,并使用上面创建的布局参数params。
当root==null||!attachToRoot,将temp赋值给result。
最后,将result返回。

逻辑看起来较繁琐,简单点可以这么理解。
只要root==null,无视attachToRoot的值,创建temp对象,返回temp。
当root!=null时,分两种情况。一,attachToRoot==true,将temp添加到root中,并使用布局参数params,返回root。二,attachToRoot==false,为temp设置布局参数params,返回temp。

(3).inflate()方法代码示例
在上面对inflate(int resource, ViewGroup root, boolean attachToRoot)方法的源码分析中,关于参数和返回值及其中的逻辑不难理解,主要是方法内是否为temp设置布局参数有些难以理解。下面使用代码示例进行说明。

创建MainActivity,并设置界面布局activity_main.xml。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/layout"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"/>

新建一个textview.xml。这里故意给TextView的layout_width和layout_height设定了固定数值,并添加layout_gravity属性。方便后面看出差异。

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="230dp"android:layout_height="80dp"android:layout_gravity="center_horizontal"android:background="#999999"android:text="blog.csdn.net/ruancoder"android:textColor="#ffffff"android:textSize="18sp"/>

在MainActivity的onCreate()方法中,添加如下代码。

<pre name="code" class="java">package net.csdn.blog.ruancoder;import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ViewGroup root = (ViewGroup) findViewById(R.id.layout);View textView = LayoutInflater.from(this).inflate(R.layout.textview, null);root.addView(textView);}
}

运行效果图一: 然后,将onCreate()方法中的代码修改为如下:

ViewGroup root = (ViewGroup) findViewById(R.id.layout);
LayoutInflater.from(this).inflate(R.layout.textview, root, true);

ViewGroup root = (ViewGroup) findViewById(R.id.layout);
View textView = LayoutInflater.from(this).inflate(R.layout.textview, root, false);
root.addView(textView);

两种方式中的任意一种。

然后再看运行效果。

运行效果图二:

从图一的显示效果可以看出,我们为TextView设定的layout属性都失去了作用。而在图二中,这三个layout属性都正常显示出来了。

inflate()方法详解和源码分析相关推荐

  1. 并发编程五:java并发线程池底层原理详解和源码分析

    文章目录 java并发线程池底层原理详解和源码分析 线程和线程池性能对比 Executors创建的三种线程池分析 自定义线程池分析 线程池源码分析 继承关系 ThreadPoolExecutor源码分 ...

  2. 史上最详细的ConcurrentHashMap详解--源码分析

    ps.本文所有源码都是基于jdk1.6 首先说明一点,ConcurrentHashMap并不是可以完全替换Hashtable的,因为ConcurrentHashMap的get.clear函数是弱一致的 ...

  3. SpringBoot入门详解源码分析

    注:文章内容来自于黑马的虎哥,个人感觉写的挺好的,所以只是做了简单整理,我只是文章的搬运工! # 0.学习目标 - 了解SpringBoot的作用 - 掌握java配置的方式 - 了解SpringBo ...

  4. python列表两两相减_用Python做打字软件,让你的打字快如闪电!附超详解和源码链接

    版本正在更新--,目前1.3.2 项目结果 GIF制作十分粗劣,自己看着都揪心,不过基本看清楚了 详细解释 下面我会详细解释一下,如果不看,就不看吧,直接向下看源码,传送门 基本结构+标题标签+提示+ ...

  5. 桌面便签程序的实现详解和源码 (下)

    来自:http://blog.csdn.net/silenceburn/article/details/6094705 在上半部分中,已经实现了一个可以运行的widget,但是没有任何业务功能, 因此 ...

  6. 桌面便签程序的实现详解和源码 (上)

    来自:http://blog.csdn.net/silenceburn/article/details/6093074 桌面便签软件是android上常用软件的一种,比如比较早的Sticky Note ...

  7. 让你的打字快如闪电!用Python做打字软件,附超详解和源码链接

  8. 特征选择方法详解Part2-卡方检验、互信息(Mutual Information)

    Content 1. 单变量分析 1.1 卡方检验 1.1.1 原理 1.1.2 使用示例 1.2 互信息(Mutual Information) 1.2.1 原理 1.2.1.1 互信息(Mutua ...

  9. C#高级编程——C#扩展方法+接口,定义统一的搜索接口,基于Unity(三)——图文详解加源码

    C#高级编程--C#扩展方法+接口,定义统一的搜索接口,基于Unity(三)--图文详解加源码 前言

  10. aes js加密php解密实例,基于PHP和JS的AES相互加密解密方法详解(CryptoJS)_PHP_JS_AES源码...

    [实例简介] 基于PHP和JS的AES相互加密解密方法详解(CryptoJS)_PHP_JS_AES源码 [实例截图] [核心代码] 基于PHP和JS的AES相互加密解密方法详解(CryptoJS)_ ...

最新文章

  1. Failed to load JavaHL Library(windows和mac)
  2. 选择性模糊及其算法的实现。
  3. mysql删除重复的判断_MySQL中查询、删除重复记录一共有多少种方法?
  4. Linux学习系列之Nginx调优实战
  5. OSGI嵌入jetty应用服务器
  6. 论文学习5-NODE2BITS: Compact Time- and Attribute-aware Node Representations for User Stitching
  7. 天线效应产生原因及解决办法
  8. 精美教师说课试讲教学通用PPT模板
  9. Js 嵌套if选择结构
  10. .NET连接IMB DB2数据库的一些问题及最终完美解决方案!
  11. 全球与中国高效无气油漆喷涂机市场深度研究分析报告
  12. 体验卓越品质 新贵Whql认证鼠标
  13. Android新浪微博授权提示:文件不存在 C8998 的终极解决方法
  14. 299. 猜数字游戏 js实现
  15. java 中利用subString 截取字符串中第三个/后面的内容,并将/用代替
  16. JS—随机三个0-9不重复的随机数
  17. Docker基础(上)
  18. 将两个或多个数组进行合并
  19. 计算机毕业设计Java企业员工工资管理系统
  20. 交叉熵损失函数(Cross Entropy Loss)

热门文章

  1. 使用session验证输入的验证码是否正确
  2. [打新技巧]打新股产品跷跷板定律
  3. tf.train.Saver()
  4. android电脑局域网传输方案,通过WiFi文件传输在Android和PC之间传输文件 | MOS86
  5. python画布组件_Python Tkinter 画布(Canvas)
  6. 人可以活很多次,但是七年就是一辈子
  7. Nmap的下载与基本命令运用
  8. 计算机中 空间局限性(Spatial Locality)与时间局限性(Temporal Locality)
  9. Python AngryBirds完整代码+讲解
  10. DTCMS 栏目调用方法