前言
根据Android事件分发机制一文中我们初步了解了Activity的UI视图结构,分别是Activity PhoneView DecorView ViewGroup view 这些。我们也都知道View的主要工作流程是依靠三大方法:onMeasure、onLayout、onDraw。其中measure确定View的测量宽高,layout根据测量的宽高确定View在其父View中的四个顶点的位置,而draw则将View绘制到屏幕上,这样通过ViewGroup的递归遍历,一个View树就展现在屏幕上了。
简单了解下Window、DecorView、ViewRoot
1.window是view的直接管理者,所有视图都是通过window来实现的,view不能单独存在,必须依附在window这个抽象概念.
2.每个activity都对应一个窗口window(是个抽象类),PhoneWindow是window的唯一实现类,PhoneWindow对应的布局是DecorView(装饰视图,界面的根View),是一个FrameLayout,DecorView内部又分为两部分,一部分是ActionBar(标题栏,可在配置清单文件中取消),另一部分是ContentParent,即activity在setContentView对应的布局。
3.ViewRoot对应于ViewRootImpl类,每个window对应一个DecorView和ViewRootImpl,它是连接WindowManager和DecorView的纽带,View的三大流程均是通过ViewRoot来完成的。在ActivityThread中,当Activity对象被创建完之后,会将DecorView添加到Window中,同时会创建对应的ViewRootImpl,并将ViewRootImpl和DecorView建立关联,并保存到WindowManagerGlobal对象中。ViewRootImpl用于绘制view,传递各种event事件。注:是在resume时将decorView加载上来的。
一、绘制流程源码路径
1、绘制入口
ActivityThread.handlerResumeActivity
--> WidowManagerImpl.addView(decorView, layoutParams)
--> WindowManagerGlobal.addView()
2、绘制的类和方法
ViewRootImpl.setVIew(decorView, layoutParams, parentView)
-->ViewRootImpl.requestLayout()
-->scheduleTraversals() --> doTraversals() --> performTravesals()
3、三步骤
ViewRootImpl.performMeasure //测量
ViewRootImpl.performLayout // 布局
ViewRootImpl.performDraw // 绘制
这边就不过多的分析源码了,感兴趣的小伙伴可以追踪一下源码,这里就贴一下整体的时序图。
顺带提一嘴UI刷新的方法以及区别:
Android上的刷新无非3种方法invalidate()、postInvalidate()、requestLayout(),而各种控件最后调用的刷新方式,也是通过这3种方法来实现。
1.invalidate调用后只会触发Draw 过程。
2.requestLayout 会触发Measure、Layout过程,如果尺寸发生改变,则会调用invalidate。
3.当涉及View的尺寸、位置变化时使用requestLayout。
4.当仅仅需要重绘时调用invalidate。
5.如果不确定requestLayout 是否触发invalidate,可在requestLayout后继续调用invalidate。