setContentView()绘制流程源码分析:

先从Activity 中的onCreate()中开始寻找如图:

Android view绘制流程源码 安卓绘制源码_UI

然后点开发现在Activity中调用了其中的setContentView如图:

Android view绘制流程源码 安卓绘制源码_android view绘制流程_02

再往下走会找到一个Window 抽象方法,

Android view绘制流程源码 安卓绘制源码_抽象方法_03

而在这里这个抽象方法的头部写着:

Android view绘制流程源码 安卓绘制源码_Android view绘制流程源码_04

标识着这个抽象的方法的唯一的实现类就是这个PhoneWindow.也就是说上边的Activity中调用的SetContentView 会最终调用到这PhoneWindow中

Android view绘制流程源码 安卓绘制源码_抽象方法_05

在这个PhoneWindow当中主要做了两件事情:

1:installDecor()    加载布局容器

2:加载解析自己写的布局。

在这里需要对上边的内容进行简单的归纳:在Activity中是用继承子Window的PhoneWindow来实现SetContentView的 而其中它实现了重要的两步,加载了系统基础布局,然后解析了自己写的布局。

Android view绘制流程源码 安卓绘制源码_加载_06

这是DecorView默认的一个渲染,然后我们自己的布局都是渲染到她的FrameLayout上的

那么在这里我们现在能够明白,installDector其实实际上是在初始化两个视图容器,然后加载系统的R资源及特征,产生了一个基本布局

那么接着回到之前我们关注的另外一个方法mLayoutInflater.inflate(layoutResID, mContentParent);

这个方法就比较好理解了,

Android view绘制流程源码 安卓绘制源码_android view绘制流程_07

这这段注释上面我们就可以得到一个信息

//Inflate a new view hierarchy from the specified xml resource.(从指定的视图当中获取试图的层次结构,意思就是,现在在加载自己的资源)

而具体流程就不贴代码了给各位上一张图

Android view绘制流程源码 安卓绘制源码_android view绘制流程_08

这个就是解析布局的步骤。

在解析View渲染之前在说一个重要的方法:WindowManager

首先要看的就是最顶层的一个接口:这个接口中声明了三个方法

Android view绘制流程源码 安卓绘制源码_加载_09

然后下边又有一个继承自接口的接口:

Android view绘制流程源码 安卓绘制源码_抽象方法_10

最后是一个他的实现类:在ActivityResumeLaunchActivity中也就是这个大哥来管理布局容器和布局属性的。而在这个来中的第一行代码中有个WindowManagerGlobal对象,而且还是通过单例的模式来获取这个对象的,这个类中是干啥 的呢点进去看一下:

Android view绘制流程源码 安卓绘制源码_android view绘制流程_11

在这个类中可以看到有获取单例的方式,以及获取一个ServiceManager服务的Binder对象,

Android view绘制流程源码 安卓绘制源码_Android view绘制流程源码_12

还有下边获取RootView() WindowsView()的方法,以及下边最最最最重要的addView()方法,在上边ActivityThread中的addView()最终就是调用到这里的addView().下边重点研究一下这个addView()方法的具体实现。


Android view绘制流程源码 安卓绘制源码_Android view绘制流程源码_13

Android view绘制流程源码 安卓绘制源码_UI_14

在这个addView中最重要的就是下边三行代码:

Android view绘制流程源码 安卓绘制源码_Android view绘制流程源码_15

把view  root  wparams三个对象分别放到对应的集合当中,然后通过ViewRootImpl对象中setView()方法把三个进行关联...

进入addView之后我们发现了一段这样的代码,他将视图,和参数还有我们的一个ViewRoot对象都用了容器去装在了起来,那么在此处我们可以得出,是将所有的相关对象保存起来

mViews保存的是View对象,DecorView

mRoots保存和顶层View关联的ViewRootImpl对象

mParams保存的是创建顶层View的layout参数。

而WindowManagerGlobal类也负责和WMS通信

而在此时,有一句关键代码root.setView,这里是将我们的参数,和视图同时交给了ViewRoot,那么这个时候我们来看下ViewRoot当中的setView干了什么?继续往下找,这次需要在ViewRootImpl中来找了,

Android view绘制流程源码 安卓绘制源码_android view绘制流程_16

然后在这个addVIew()方法中有个最重要的方法就是requestLayout() 其余的都是垃圾。可以不用看同时这行代码上边有个最长的注释,也就说明了这行代码的重要i行了。继续往下找~

Android view绘制流程源码 安卓绘制源码_Android view绘制流程源码_17

在这里里边有三个代码,这里有两行重要的代码:

1:checkThread();看到这个throw 的Exception 熟悉吧,这不就是程序中子线程更新UI报的异常?开发人员应该都遇到过这个异常吧,在渲染布局前检查了一下当前的线程是不是主线程,如果不是主线程那么不允许更新UI...明了了吧.........

Android view绘制流程源码 安卓绘制源码_android view绘制流程_18

2:然后继续往下看下边的一行代码:

Android view绘制流程源码 安卓绘制源码_加载_19

其实回调中后调用就是doTraversal() 方法,而这个方法 中调用到了performTraversals() 方法。看到这个方法就表示着UI可以开始渲染了......开心吧,上边这麽多行代码就是到这才开始的绘制渲染流程....

不截图了太麻烦了简单总结上边的流程:

Android view绘制流程源码 安卓绘制源码_加载_20

看这麽多行代码最后如果都记不住,就记住这个方法就行了....

performTraversals()

View绘制从ViewRoot的performTraversals方法开始,经过measure、layout、draw三个过程,然后将View绘制出来

measure方法用于测量View的宽高

layout方法用于确定View在父容器中的位置

draw方法负责将View绘制在屏幕上

如下是performTraversals的流程图:

Android view绘制流程源码 安卓绘制源码_抽象方法_21