在Activity布局加载流程源码分析(I)、Activity布局加载流程源码分析(II)、DecorView绘制流程源码分析与View绘制三大流程源码分析等四篇文章中,已经很详细分析了Acitivity的布局加载过程及布局的绘制过程。但在Activity布局加载流程源码分析(I) 中,对于setContentView(“资源文件”)怎么转化View的,没有细说,本篇博文主要想梳理一下这块内容(ps:面试的时候,被面试官问到,既然答不上来,所以决定对这部分知识也好好梳理一下)。
在开始分析之前,我们需要了解一些概念,如:
- PhoneWindow: 是Window类具体实现类,Activity中布局加载逻辑主要就是在此类中完成的。
- LayoutInflater: 是布局填充类,主要就是将我们的layout转化为View。
- XmlPullParser: 是XML解析器,主要是解析xml文件也即layout.xml文件。
一、源码分析
从Activity布局加载流程源码分析(I)文中,我们知道,在Activity的onCreate()中setContentView()后,最后也是调用PhoneWindow中的setContentView()方法。源码如下:12345//Activity中public void setContentView(int layoutResID) {getWindow().setContentView(layoutResID);//核心代码initActionBar();}
|
|
这里我们主要来看核心代码,也即 mLayoutInflater.inflate(layoutResID, mContentParent);其中mLayoutInflater的初始化主要是在PhoneWindow中构造方法中初始化的:
所以,重点我们还是来看一下LayoutInflater类:
从上面代码我们知道,mLayoutInflater 的初始化,主要是从context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)中获取的。在LayoutInflater的源码中,还有多个inflate方法中,这里我们先来看看填充方法2:
由代码易知,这里主要是从资源Resources中获取布局xml,通过res.getLayout(resource)得到一个Xml资源解析器XmlResourceParser,然后再调用填充方法4,这里的XmlResourceParser,我们也可以来看一下源码:
由上易知,XmlResourceParser也是一个接口,这里主要继承了三个类XmlPullParser(XML文件解析器)、AttributeSet(自定义属性值)、AutoCloseable ,主要是了后面解析服务。所以这里我们重点来看看Resource中的getLayout()方法:
通过上面代码我们知道,最后通过XmlBlock.newParser()生成一个xml解析器,也即是XmlResourceParser,从以上我们知道Android中布局文件用的xml解析方法就是PULL解析方式。 下面我们具体来看填充方法4:
我们在写布局文件的时候,经常也会考虑到一些布局优化的问题,所以难免会用到include、merge、ViewStub标签,所以在XML解析的时候,需要针对此类标签作特别处理。
从上面代码中,我们来看核心代码1, TAG_MERGE.equals(name),其中 TAG_MERGE就为merge,这里主要就是针对merge标签处理。我们先来看核心代码3和4,
核心代码3: createViewFromTag(root, name, inflaterContext, attrs),具体我们也来看看源码:
我们也来看看核心代码4:rInflateChildren(parser, temp, attrs, true),我们具体来看看相关代码:
通过上面发现,最后也还是调用了核心代码2,rInflate(parser, root, inflaterContext, attrs, false),下面我们具体来看看核心代码2:
这里我们看到,主要就是通过PULL解析布局文件的方式解析出相关的View结构,具体PULL解析方式这里就不介绍了,小伙伴可以自行百度。在这里PULL解析的过程中,还对标签include,merge做了特别处理,是不是发现貌似代码中没有对标签ViewStub进行处理,其实是有的,主要是在createView()方法中,这里就不介绍了,小伙伴可以自行查一下源码。
好了,到这里,就差不多分析完了。
注:源码采用android-6.0.1_r1版本,建议下载源码然后自己走一遍流程,这样更能加深理解。