将View添加到WindowManagerService的过程
1 : ActivityThread.handleResumeActivity
从上面可知,WindowManager是通过Activity的getWindowManager获取到的
更进一步,发现WindowManager是在attach的时候被赋值的。
mWindowManager又是通过mWindow获取的,我们知道,mWindow的实际是PhoneWindow类型的。那么继续看看mWindow的实现。在PhoneWindow的父类Window中。
可知,实际的类型的是WindowManagerImpl。也就是说上面的代码实际执行了WindowManagerImpl的addView方法。
2 : WindowManagerImpl.addView
可知,mGlobal是什么类型的呢?
可知,WindowManagerImpl实际上是WindowManagerGlobal类型的,那么便执行WindowManagerGlobal的addView方法。
3 : WindowManagerGlobal.addView
从上图可知:
1.WindowManagerGlobal创建了ViewRootImpl
2.把view添加到了mRoots。
这个view是什么呢?通过下图可知,实际上便是DecorView
mRoots又是什么呢?下图可知,mRoots是ViewRootImpl的容器。另外可知,mViews是所有DecorView对应的容器。
3.执行了ViewRootImpl的setView方法。
4 : 创建ViewRootImpl,从上面的图中已经可知。
5 : ViewRootImpl.setView
ViewRootImpl执行了很多,其中最重要的是执行了mWindowSession.addToDisplay
mWindowSession是什么?
再看下WindowManagerGlobal的getWindowSession方法
WMS的openSession实现
mWindowSession实际上是SystemServer中Session的远程代理。
6 : 通过Session的远程代理,通知SystemServer进程的Session addToDisplay.
mService是什么类型的呢?
7 :Session调用WMS的addWindow方法。发现addToDisplay第一个参数是mWindow类型。mWindow是什么呢?查看代码后发现其是IWindow类型的。再回头看看ViewRootImpl传递的是什么
W类型是什么?
发现其用于进程通信的。应该是从WMS进程(System Server进程),对App进程通信的途径。
App进程 与 WMS进程(SystemServer进程)进行通信的方式
ViewRootImpl的类图结构
View的三个方法: measure、layout、draw。
measure
可知:
- 这个方法被用来得出一个view应该有多大。
- 父容器通过参数给出 宽 和 高 的约束信息。
- measure方法会调用onMeasure()
- 真正的测量工作在onMeasure里。
- 参数:父容器 对 横向/竖向 间距的要求。
- measure,方法是final的,不能够override。
onMeasure方法
可知:
- 测试当前view 以及 其内容,来得出实际的宽 和 高。
- 这个方法被measure调用。
- 当override这个方法的时候,需要调用setMeasuredDimension方法去记录这个view的实际宽高。如果没有执行这个方法,会抛出异常。
View的layout方法
可知:
- 设定一个view及其子视图的大小 和 位置(相对于父容器的位置)。
- layout是布局机制的第二步,第一步是测量measure。
- 每个父容器,对其子view调用layout方法,给子view指定位置。
- view的子类不能覆盖这个方法,而应该覆盖onLayout方法,对于每一个子view,都应该调用子view的layout方法。
- layout方法调用onLayout方法。
View的onLayout方法
可知:
- View的onLayout方法,并没有实现任何代码。
- 在layout方法中被调用。
- 含有子view的类(即ViewGroup的子类),应该override这个方法,然后对每一个子view调用layout。
ViewGroup的layout方法
可知
- ViewGroup里的onLayout方法是抽象的。(因为事实上ViewGroup并不能确定如何摆放子视图)
LinearLayout的onLayout方法
View的draw方法
可知:
- 这个方法在ViewGroup的drawChild里被调用。
- ViewGroup的每个子View都负责自己绘制自己。
View的onDraw方法
可知:
- onDraw空实现。
- 子类可以自己实现。
View的dispatchDraw
可知:
- 被draw方法调用,用于绘制子view。
- 这个方法可能被子类覆盖。