06. View工作原理

打印 上一主题 下一主题

主题 932|帖子 932|积分 2796


预习:

  • 什么是viewRoot?
  • 什么是WindowManager?
  • 什么是DecorView?
  • 为什么说ViewRootImpl 毗连了 WindowManager(外界窗口管理入口)和 DecorView(整个视图树的顶层容器)。
  • DecorView保护内容栏和标题栏,请问这是什么意思?
  • View绘制的层原理是什么?
  • 产生View卡顿的缘故原由有哪些?
01.View工作流程

1.1 View的扼要工作流程



  • View工作流程简朴来说就是,先measure测量,用于确定View的测量宽高,再 layout结构,用于确定View的最终宽高和四个顶点的位置,最后 draw绘制,用于将View 绘制到屏幕上。
1.2 View的整体工作流程



  • View的整体工作流程:

    • View的绘制流程是从ViewRoot和performTraversals开始。performTraversals()依次调用performMeasure()、performLayout()和performDraw()三个方法,对于这三个方法,他们流程大致相同,我们举performMeasure例子介绍,performMeasure()会调用DecorView的measure(),进入到视图树的逻辑当中
    • 对于View树的遍历,实在就是:DecorView–>ViewGroup(—>ViewGroup)–>View ,按照这个流程从上往下,逐层迭代,依次measure(测量),layout(结构),draw(绘制)。具体是是:Decorvie的measure()中又调用onMeasure(),实现对其所有子元素的measure过程,如许就完成了DecorView的测量过程;接着View树中的子元素会重复父容器的measure过程,如此反复至完成整个View树的遍历。layout和draw同理。

    • ViewRoot对应于ViewRootImpl类,它是毗连WindowManager和DecorView的纽带。

  • 比较重要的概念

    • ViewRoot:毗连WindowManager(外界访问Window的入口)和DecorView(顶级View)的纽带,View的三大流程均是通过ViewRoot来完成的。
    • DecorView:顶级View

      • DecorView是顶级View,本质就是一个FrameLayout
      • 包含了两个部分,标题栏和内容栏
      • 内容栏id是content,也就是activity中setContentView所设置的部分,最终将结构添加到id为content的FrameLayout中


  • View的绘制是从上往下一层层迭代下来的。DecorView–>ViewGroup(—>ViewGroup)–>View ,按照这个流程从上往下,依次measure(测量),layout(结构),draw(绘制)。



02.View底层绘制原理



  • 上述的measure、layout和draw等都是Android Framework层。但是仅凭这些但是无法完成整个绘制过程的。好比,图形怎么转化为像素,差别图层怎样合成?事实上,View的绘制由三个层次的配合实现,分别是Android Framework层(Java层),图形驱动层(Native层),Linux系统层(SurfaceFlinger)
  • 起首是Android Framework层(Java层)

    • 调用cpu处理View树结构,实行 measure、layout 盘算使命
    • 在Draw阶段生成绘制指令(Display List),并提交Display List到图形驱动队列

  • 然后是图形驱动层:

    • 从队列读取Display List
    • 栅格化(将矢量图形转为像素)
    • 实行渲染操作,并输出像素数据到帧缓冲区

  • 最后是内核服务层(SurfaceFlinger):其会集成多个图层(如应用UI、状态栏、导航栏),具体来说如下:

    • 接收各图层的像素数据
    • 进行合成操作
    • 通过硬件混合器(HWC)输出到显示装备

03.View卡顿丢帧原理



  • 明确View绘制的底层原理后,我们就可以尝试去明确View为什么卡顿掉帧了。
  • 什么是掉帧:

    • 对于60fps的显示,也就是1s内渲染60次,也就是大概每隔16ms(1000 / 60)就要渲染一次。Android系统每隔16ms发出VSYNC信号,触发对UI进行渲染,如果每次渲染都成功,如许就能够达到流畅的画面所需要的60fps,VSYNC是Vertical Synchronization(垂直同步)的缩写,是一种定时中断,一旦收到VSYNC信号,CPU就开始处理各帧数据。
    • 如果某个操作要耗费30ms,总耗时超过 16ms,如许GPU无法在下一个VSYNC信号前完成渲染。系统只能扬弃当前未完成的帧,重复显示上一帧画面。这就是丢帧卡顿。

  • View掉帧卡顿的缘故原由主要分为:cpu阶段和gpu阶段,其中cpu阶段分为耗时和UI线程卡顿。GPU阶段则是负载压力大,无法及时渲染出来。

    • cpu阶段:

      • 耗时:

        • 结构嵌套层级过深:每个视图层级都会增加 measure 和 layout 的复杂度。过深的嵌套层级,导致 measure 和 layout 阶段耗时过长。

      • UI线程卡顿:

        • 在 UI 线程中实行耗时操作,Android中UI更新是依靠于UI单线程实行,如果在里面实行播放视频等耗时使命,会壅闭 UI线程进行UI 更新的操作。
        • GC(垃圾回收)暂停时间过长大概频繁的GC产生大量的暂停时间。其中GC 暂停会暂停应用线程,而频繁的GC是指好比在OnDraw中分配对象,其每次绘制都会调用,实行完成后都会回收,会导致频繁的内存分配和垃圾回收(GC)。


    • gpu阶段:

      • 动画过于复杂:动画结果复杂,过度绘制,使得GPU负载压力大,无法及时渲染出来。


04.自界说View优化计谋

为了加速你的View,你要做到符合如下要求:


  • 扁平化视图层级:每个视图层级都会增加 measure 和 layout 的复杂度。扁平化视图层级可以减少measure和layout的调用
  • 自界说 ViewGroup 优化结构逻辑:默认的 ViewGroup 测量逻辑会遍历所有子视图,可能造成性能浪费。我们可以 通过自界说ViewGroup的测量逻辑来优化性能
  • 克制在 onDraw 中分配对象:这会导致频繁的内存分配和垃圾回收(GC)。
  • 优化invalidate:调用 invalidate() 会触发 onDraw,过于频繁的 invalidate() 调用会增加 CPU 和 GPU 的负担。因此要符合如下要求:

    • 克制不必要的 invalidate() 调用。
    • 如果只需要更新部分地域,利用带四个参数的 invalidate(left, top, right, bottom) 方法,限制重绘地域。

其他介绍

01.关于我的博客



  • csdn:http://my.csdn.net/qq_35829566
  • 掘金:https://juejin.im/user/499639464759898
  • github:https://github.com/jjjjjjava
  • 简书:http://www.jianshu.com/u/92a2412be53e
  • 邮箱:[934137388@qq.com]

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

徐锦洪

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表