59

setContentView是如何一步一步被显示出来的?

 5 years ago
source link: http://www.10tiao.com/html/272/201807/2666454249/1.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

通常我们在onCreate中会调用setContentView方法,如下:


image.png


setContentView里面优势怎么样执行的呢,进去看看,如下:


image.png

跳转到getWindow().setContentView(layoutResID)如下:


image.png

Window类型的继承树如下:


image.png


Window只有一个实现类PhoneWindow,那也就是说getWindow().setContentView(layoutResID)调用的是PhoneWindow的setContentView,如下:


image.png


先来看看上图中标记A的地方,调用installDecor方法,看名字的意思是创建decor的意思,而这个decor如果你熟悉Adroid 视图的层级结构的话,会一下子就理解,这里我给一张图帮助你理解:

无标题.png

DecorView实际上是作为Activity上的视图的最顶层View,而我们自己的布局则是上图粉色区域,外面还包含着一层,称之为contentParent,从名字上看也是取得很贴切,嗯还是进入源码看看一下是不是上图描述的那样,如下:


image.png


genereteDecor方法调用如下:


image.png


generateLayout方法如下:

image.png

至此可以看到最顶层布局,以及我们自己的布局的复布局都已创建好了,回到上图标记B 的地方,可以看到调用了    mLayoutInflater.inflate(layoutResID, mContentParent);
这个layoutResID就是我们自己的布局的id,调用完这一句我们自己的布局也被创建出来了,到这里你应该会有一个疑问:Activity的整个View视图都被创建好了,那么接下来应该是要绘制这个视图才对,我第一次看这个源码的时候也是有这个疑问,同时还犯了一个错误,我试图在mLayoutInflater.inflate(layoutResID, mContentParent);这句之后查找开启绘制试图的代码,查看源码我根本就找不到,一下子就懵逼了,如下:


image.png

其实这是我忽略了一个事实,这个setCotentView 是在onCreate被调用的这个时候View是不能见,真正能见的是在onResum时候,对哦,恍然大悟!!如果你有阅读之前的那篇Activity生命周期回调是如何被回调的?应该会知道onResume何时开始被调用,如下:

image.png


image.png


上图这个方法是在ActivityThread类中的,看到标记E的地方,是开始Activity的onResume的调用,进去看看,如下:


image.png

进入wm.addView看看如何,调用的是它的实现类WindowManagerImpl的addView如下:


image.png


跳转如下:


image.png


ViewRootImpl调用setView如下:

image.png


setView方法里面调用了requestLayout,这个方法名让我们看到了是在做绘制View视图的苗头,进去看看是不是如此:


image.png


image.png


mTraversalRunnable对象的类相貌如下:

image.png


可以看到在run方法里面调用doTraversal,如下:


image.png

performTraversals方法的代码是在是太长了,这里我不截图,这个方法里面调用了三个关键的方法:performMeasure方法开启视图的测量流程,performLayout方法开启了视图的布局流程,performDraw开启了视图的绘制流程,这3个方面的具体细节我准备在其他篇章来介绍,这3个流程走完,视图就会被真正的绘制完成。到此setContentView的工作是如何一步一步被现实的,你是否有一个比较深的理解了,回顾一下前面讲的东西,可以总结如下:

1.setContentView只是将Activity的整个View视图创建好,放在一边而已,而执行创建View视图的则是PhoneWindow

2.在Activity在准备转换成Resume状态的之际,即调用handleResumeActivity,会将最顶层View——DecorView兜兜转转传到WindowManagerGlobal 手中

3.DecorView在WindowManagerGlobal 手中,首先先添加进View数组方便管理同时会为这个DecorView也可以说是这个视图创建一个ViewRootImpl

4.ViewRootImpl 将调用setView 将DecorView传入,开启绘制之旅

5.所以从前四步来看,真正导致Activity整个视图会被绘制的罪魁祸首是WindowManagerGlobal



作者:钟离四郎
链接:https://www.jianshu.com/p/d36398c9d498
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

                        喜欢 就关注吧,欢迎投稿!




About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK