Android-View的工作流程

View的工作流程

measure:

  • View
  • ViewGroup

layout:

  • layout()
  • onLayout()

draw:

draw()中调用的4个方法


PhoneWindow是窗口类,继承自抽象类Window,也是唯一子类。WindowManager是Window管理接口,继承自ViewManager,他的唯一实现类是WindowManagerImpl。WindowManagerImpl并没有真正实现windowManager接口逻辑,而是把逻辑转给了WindowManagerGlobal,WindowManagerGlobal是全局单例。Window和View的联系通过ViewRootImpl桥梁,同时ViewRootImpl还负责管理view树、绘制view树、和WMS通信。WMS即WindowManagerService,是Window的真正管理类。

img

measure------->layout-------->draw

测量-------布局-------绘制

  1. 确定View的测量宽高

  2. 确定View的最终宽高和四个顶点的位置

  3. 将View绘制到屏幕上

  • measure:完成测量过程。由**(final型,不能重写)**measure()方法来完成

    • View的measure()方法中会调用View的onMeasure()方法
    • 如果是ViewGroup则会遍历调用所有的子元素的measure方法-----measureChildren()
      • 对于ViewGroup来说,除了完成自己的measure过程,还会遍历去调用所有子元素的measure方法,各个子元素在递归去执行这个过程。和View不同的是,ViewGroup是一个抽象类,因此它没有重写View的onMeasure方法,但是他提供了一个叫measureChildren的方法。
  • Layout:作用:ViewGroup用来确定子元素的位置

    • layout()方法确定View本身的位置
      • 通过setFrame()方法设定View的四个顶点的位置
      • 调用onLayout()方法:父容器确定子元素的位置
    • onLayout()方法确定所有子元素的位置。(onLayout()是在layout()中被调用个)
      • 在onLayout()方法中调用子元素的layout()方法
      • 层层传递,则可完成整个View树的layout过程
  • draw:将View绘制到屏幕上。

    这4个方法全包括在draw()方法里面调用

    • 绘制背景 drawBackground(canvas)
    • 绘制自己( onDraw(canvas) )
    • 绘制children(dispatchDraw(canvas) )
      • dispatchDraw会层层遍历所有子元素的draw方法
    • 绘制装饰(onDrawScrollerBars(canvas) )

View绘制的过程的传递通过dispatchDraw()来实现的,它会调用所有子元素的draw方法


那么发起绘制的入口在哪里呢?

在介绍发起绘制的入口之前,我们需要先了解Window,ViewRootImpl,DecorView之间的联系。

一个 Activity 包含一个Window,Window是一个抽象基类,是 Activity 和整个 View 系统交互的接口,只有一个子类实现类PhoneWindow,提供了一系列窗口的方法,比如设置背景,标题等。一个PhoneWindow 对应一个 DecorView 跟 一个 ViewRootImpl,DecorView 是ViewTree 里面的顶层布局,是继承于FrameLayout,包含两个子View,一个id=statusBarBackground 的 View 和 LineaLayout,LineaLayout 里面包含 title 跟 content,title就是平时用的TitleBar或者ActionBar,contenty也是 FrameLayout,activity通过 setContent()加载布局的时候加载到这个View上。ViewRootImpl 就是建立 DecorView 和 Window 之间的联系。

这三个阶段的核心入口是在 ViewRootImpl 类的 performTraversals() 方法中。绘制的入口是由ViewRootImpl的performTraversals方法来发起Measure,Layout,Draw等流程的。

private void performTraversals() {
    ......
    int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
    int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height);
    ......
    mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
    ......
    mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight());
    ......
    mView.draw(canvas);
    ......
 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值