先来解释一下LayoutInflater这个名字,Inflater在英语的意思是打气筒,直一点的翻译就是 布局的打气筒,发挥一下想象力,就是我们用一个特定的打气筒,对代码泵气,一点一点地泵成我们看到的界面。
虽然很多人对它很陌生,但是其实我们经常使用到它,因为加载布局的任务通常都是在Activity中调用setContentView()方法来完成的,而setContentView()方法的内部也是使用LayoutInflater来加载布局的。
分析之前我们先要把打气筒拿过来,一共有两种方法:
1、LayoutInflater layoutInflater = LayoutInflater.from(context);
2、LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
然而,其实第一种只是第二种的封装。我们可以看到这个“打气筒”竟然是SystemService,系统服务,我们向系统借了个“打气筒”啊。
有了“打气筒”,就可以开始给代码“打气”了。(注,这里的代码指的是xml布局文件)
泵气前,需要解决两个问题:给哪段代码打气,打完气的界面放在哪里。于是,决定了这两个问题的答案以后,我们开始打气了:
layoutInflater.inflate(resourceId, root);
inflate()方法一般接收两个参数,第一个参数就是要加载的布局id,第二个参数是指给该布局的外部再嵌套一层父布局,如果不需要就直接传null。这样就成功成功创建了一个布局的实例,之后再将它添加到指定的位置就可以显示出来了。
就是说,我们甚至可以先打气,打好气再决定成品的放置位置。
ok,现在我们再去看看这个打气筒内部是如何工作的。我们准备用这个打气筒给一个xml布局文件打气:
以上三段代码都非常简单,任何Android基础的都应该能看懂(看不懂的话说明你不应该看这篇文章)。定义了一个Activity的布局文件,作为父View,再定义了一个button的布局(button_layout。xml),用LayoutInflater将button的xml实例化为一个可用的view,再把这个view放置到之前的父View中。
拆开这个打气筒之前,我们先来设想一下如果是有我们自己来实现这个打气筒,我们该如何做。我们拿到手的xml,会包含很多的标签,标签和标签间会相互嵌套。于是很多人几乎脱口而出了:递归解析!于是我们开始构思:
先把这xml拿好,放在地上,从头开始看,先把根View的属性都那出来,根据根View的类型和属性构建一个View,构建完成以后,我们再往下遍历,遇到子标签就把子标签的整个内容扔回到这个方法,进行构建,如此递归到底,就把整个xml成功泵成一个View了。
拆开这个打气筒,我们发现:不管你是使用的哪个inflate()方法的重载,最终都会辗转调用到LayoutInflater的如下代码中(部分调试输出被删除):
(我觉得文档也挺有用的,所以也贴了上来)
(再次吐槽,简书贴的代码的排版很丑,所以只好截屏)
看完源码,发现基本思路差不多。只是“子View递归”似乎不太一样,是的,这里子View的“打气”交给了rInflateChildren完成,而rInflateChildren指向的是rInflate方法。
(顺便猜测一下,为什么和我们预期的递归不一样呢,个人的想法的是:View和ViewGroup是不一样的!虽然是废话,但这就决定了root View的“打气”跟子View的“打气”是不一样的)
代码挺简单的,就不过多解释了,只是说一下的是,这段代码由出现了Android的三个特殊标签(RequestFocus、Include、Merge,还有一个是ViewStub也是特殊的标签)。这个几个标签对UI布局优化非常重要,没了解的朋友应该去了解一下。
OK,到这里,这个布局的“打气筒”也差不多解释到这里了,可以总结一下:
1、我们向系统申请借来了一个LayoutInflater,即布局的打气筒;
2、我们给这个打气筒接上需要被打气的XML布局文件;
3、我们泵了第一下的气,就把root View的模型泵胀了;
4、借着我们继续用力,泵了几下气,root View中的第一个标签也被泵胀了,如此泵下去,第一层嵌套的最深的view都被泵好了;
5、被泵好(注意泵好和泵胀的区别)的view就贴到上一层的父view上;
6、第5步的父view继续泵它的下一个子view;
7、如此递归,第5步的父view的所有子view都泵好了,并把子view贴到这个父view上,这个父view宣布自己也被泵好了,也贴到了自己的父view上;
8、如此递归,所有的view(包括root view)都被泵好,泵气结束;
Reference:http://blog.csdn.net/guolin_blog/article/details/12921889
写在文尾:
1、本文是看了 郭霖 大牛的View解析系列(参看上文的Reference)以后,结合着源码, 按着自己的理解写的,如有错漏或理解不当,烦请指出;
2、装载请表明出处:http://www.jianshu.com/p/e0f63741e77b#
3、本人广州一大三软件狗,请问有广东地区的公司收Android实习生吗,可扫地