详解Android布局加载流程源码
一.首先看布局层次 看这么几张图
我们会发现decorview里面包裹的内容可能会随着不同的情况而变化,但是在decor之前的层次关系都是固定的。即activity包裹phonewindow,phonewindow包裹decorview。接下来我们首先看一下三者分别是如何创建的。
二.activity是如何创建的
首先看到入口类activitythread的performlaunchactivity方法:
有句特别关键的代码,即
所以activity是instrumentation类的newactivity方法创建的,追踪过去,源码如下
追踪源码,可知getfactory方法返回一个appcomponentfactory对象,然后调用appcomponentfactory的instantiateactivity方法,继续追踪
到这里就结束了,我们可以发现activity是通过反射创建的。
三.phonewindow的创建
我们还是回到activitythread的performlaunchactivity方法,在刚刚展示的那一段的下面有如下部分代码
在activity.attach这个方法中,传入了一个window对象,追踪这个attach方法,里面有一句关键代码
此时就创建了phonewindow。所以我们可以知道,在activity创建完之后,会为当前的activity创建一个phonewindow对象。
四.decorview的创建
decorview的创建就不是performlaunchactivity方法里面了,这次我们从activity的setcontentview的源码开始分析。下面的activity的setcontentview方法的内容。
我们发现,activity的setcontentview实际是调用了phonewindow的setcontentview方法,跟踪源码。我们会首先进入window抽象类,然后我们找其子类phonewindow,在里面找到setcontentview方法
当mcontentparent为null时,会调用installdecor方法,追踪进入
它调用了generatedecor方法,追踪进入
会发现generatedecor方法会创建一个decorview对象,并且作为返回值返回。再追踪decorview
会发现decorview其实是一个framelayout 。到这就介绍完decorview是如何创建的了
五.布局加载流程
我们回到phonewindow的installdecor方法,再刚刚看的部分的下面,有(2692行)
追踪进入
分析源码和源码注释可以看出generatelayout方法的核心功能是完成decorview的布局加载,而且根据不同的主题样式会加载不同的系统默认布局。那么比如有framelayout布局,它如何加载到decorview中呢?
在generatelayout方法中,有这么一句
追踪进入
关键在这里
可以看到layoutresource作为参数,通过inflate方法进行解析加载。然后作为参数,传入addview方法,将布局挂载到上面。至此完成了decorview的默认布局加载。如果是我们自己编写的布局是如何加载呢?再回到generatelayout的
,在此之后,有这么一句
在decorview执行onresourcesloaded方法加载完默认布局后,会查找id为id_android_content的控件(默认布局中的framelayout控件)并作为generatelayout方法的返回值,我们回到setcontentview方法中,可观察到以下代码:
所以,我们自己编写的布局是被加载到decorview中id为id_android_content的控件上
六.总结
当activity创建后会创建出一个phonewindow对象,当在activity中调用setcontentview时,实际上是调用了phonewindow的setcontentview方法,此时phonewindow会创建根布局decorview,并根据主题样式,为decorview加载对应的默认系统布局,在默认的系统布局中包含了一个id为id_android_content的控件,而我们自己编写的布局就是加载到这个控件中的。
以上就是详解android布局加载流程源码的详细内容,更多关于android布局加载流程源码分析的资料请关注其它相关文章!