View的绘制流程

87 阅读2分钟

Android视图层次结构

1.Measure

  • MeasureSpec
    • UNSPECIFIED
      未指定尺寸,这种情况不多,一般都是父控件是AdapterView,通过measure方法传入的模式。可以调用setMeasuredDimenson方法,将View的高度和宽度传入,设置子View实际的大小,告诉父控件需要多大的空间放置子View。
    • EXACTLY
      精确尺寸,当我们将控件的layout_width或layout_height指定为xxdp(具体数)/match_content
    • AT_MOST
      最大尺寸,当控件的layout_width或layout_height指定为warp_content时,控件大小一般随着控件的子空间或内容进行变化,此时控件尺寸只要不超过父控件允许的最大尺寸即可。
  • attr 配置文件,可以在xml布局中使用定义过的属性
TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.name);
...配置文件的读取
a.getBoolean
a.getInt
a.getDimension
...
a.recycle();

2.Layout

  • 主要会调用到onLayout(),执行顺序先控制子View的摆放顺序,再层层往上递进。
  • 一般情况下View是不需要计算Layout的,只有继承了ViewGroup才需要自己计算。

3.Draw

  • onDraw(Canvas canvas) canvas画布这里不详细说明

4.面试题

  • Window、Activity、DecorView以及ViewRoot之间的关系

    • Activity 不负责控制视图,只控制生命周期和事件等,可通过回调与window view交互。真正控制视图的是window也就是phonewindow
    • Window 其实是phonewindow,内部持有decorview,通过创建decorview来加载布局,将其交给viewroot进行视图绘制和交互
    • Decorview 是视图树的根节点,内部一般包含一个linear垂直布局,分为三个部分,bar(viewstub,根据主题来设置),title,content。
    • Viewroot 控制所有绘制,事件,对应实现类viewrootimpl,内部通过handler来进行事件分发。。事件感知是从 硬件 -> ViewRootImpl -> PhoneWindow -> DecorView -> Activity

从act.attach——》attach创建phonewindow——》act.setcontenview——》phonewindow.setcontentview——》其中如果没有android.id.content这个contentParent,先创建了decorview,如果有则先清空contentParent子view。——》decorview是先从主题中获取样式,根据样式获取布局,再获取contentParent,为他添加需要的布局。 为什么在onResume的时候显示界面? ActivityThread Handlelaunchactivity——》performLaunchActivity中,执行了activity的attach和onCreate和onStart,但只是初始化了decorview,并没有将它显示到window上——》HandleResumeactivity中调用了onResume,执行了activity.makeVisible使ui可见——》makevisible中windowmanage.addview方法(实际上是windowmanageimpl)创建了viewrootimpl,viewrootimpl.setview将DecorView交给ViewRootImpl,负责绘制处理布局。 最后调用scheduleTraversals执行绘制流程