垂直同步vsync
Surface
在 WMS 中会为这个 Window 分配 Surface,并确定显示层级,可见负责显示界面的是画布 Surface,而不是窗口本身,WMS 将他管理的 Surface 交由 SurfaceFlinger 处理,SurfaceFlinger 将这些 Surface 合并后放入到 buffer 中,屏幕会定时从 buffer 中获取显示数据,显示到屏幕上。
刷新率
在 Android 系统中,屏幕定时从 buffer 中获取显示数据的时间通常是以屏幕刷新率(刷新频率)来衡量的。常见的屏幕刷新率包括60Hz 和120Hz,表示屏幕每秒刷新60次或120次。
具体的刷新时间取决于屏幕刷新率和 VSync 信号的触发。VSync(垂直同步信号)是一个由硬件生成的信号,用于同步屏幕刷新和显示数据的传输。在每个 VSync 信号触发时,屏幕会从 buffer 中获取最新的显示数据,并将其显示在屏幕上。
以60Hz 的屏幕刷新率为例,每秒刷新60次,因此每次刷新的时间间隔约为16.67毫秒(1秒/60 = 0.0167秒 ≈ 16.67毫秒)。这意味着,屏幕会大约每16.67毫秒获取一次 buffer 中的显示数据,并更新到屏幕上。
需要注意的是,具体的屏幕刷新率和 VSync 触发时间可能因设备而异。某些设备可能具有不同的刷新率(例如90Hz 或120Hz),因此屏幕获取显示数据的时间间隔也会相应变化。此外,硬件和系统的性能也可能影响刷新时间的准确性。
VSYNC
Android 系统每隔16ms 发出 VSYNC 信号,触发对 UI 进行渲染,如果每次渲染都成功,这样就能够达到流畅的画面所需要的60fps,为了能够实现60fps,这意味着程序的大多数操作都必须在16ms 内完成。如果你的某个操作花费时间是24ms,系统在得到 VSYNC 信号的时候就无法进行正常渲染,这样就发生了丢帧现象。那么用户在32ms 内看到的会是同一帧画面。
用户容易在 UI 执行动画或者滑动 ListView 的时候感知到卡顿不流畅,是因为这里的操作相对复杂,容易发生丢帧的现象,从而感觉卡顿。有很多原因可以导致丢帧,也许是因为你的 layout 太过复杂,无法在16ms 内完成渲染,有可能是因为你的 UI 上有层叠太多的绘制单元,还有可能是因为动画执行的次数过多。这些都会导致 CPU 或者 GPU 负载过重。
cpu、gpu功能
- cpu 负责计算 measure layout draw
- gpu 负责渲染 display =>位图
- 每个16ms 会发送一次垂直同步信号 vsync
- 每次信号发送的时候都会从 gpu 的 buffer 中取出渲染好的位图显示在屏幕上,同时如果有需要还会进行下一次的 cpu 计算, 计算好后放入 buffer 中
- 如果计算时间超过了两次 vsync 之间的时间即16ms 则 vsync 信号会把上一次 gpu buffer 中的信息展示出来这时候就是卡顿
- 另外如果页面没有变化屏幕还是一样会去 buffer 中取出上一次的刷新, 只不过 cpu 不再去计算而已