预习:
- 什么是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企服之家,中国第一个企服评测及商务社交产业平台。 |