落叶知秋|程序员必懂的Android 技术之 VSYNC、 Choreographer 起源( 三 )
- 在第二个 16 ms 时间段内 , Display 本应该显示 B 帧 , 但却因为 GPU 还在处理 B 帧 , 导致 A 帧被重复显示 。
- 同理 , 在第二个 16 ms 时间段内 , CPU 无所事事 , 因为 A Buffer 被 Display 在使用 。 B Buffer 被 GPU 在使用 。 注意 , 一旦过了 VSYNC 时间点 , CPU 就不能被触发处理绘制工作了 。
为什么 CPU 不能在第二个 16ms 处理绘制工作呢?
原因是只有两个 Buffer , 缓冲区 B 中的数据还没有准备完成 , 所以只能继续展示 A 缓冲区的内容 , 这样缓冲区 A 和 B 都分别被显示设备和 GPU 占用 , CPU 则无法准备下一帧的数据 。
如果再提供一个缓冲区 , CPU、GPU 和显示设备都能使用各自的缓冲区工作 , 互不影响 。
简单来说 , 三重缓冲机制就是在双缓冲机制基础上增加了一个 Graphic Buffer 缓冲区 , 这样可以最大限度的利用空闲时间 , 带来的坏处是多使用的一个 Graphic Buffer 所占用的内存
- 在第二个 16ms 时间段 , CPU 使用 C Buffer 完成绘图工作 , 虽然还是会多显示一次 A 帧 , 但后续显示就比较顺畅了 , 有效避免 Jank 的进一步加剧 。
- 注意:是不是 Buffer 越多越好呢?这个是否定的 , Buffer 正常还是两个 , 当出现 Jank 后三个足以 。
3、Choreographer
Choreographer 也是 Project Butter 计划新增的机制 , 用于配合系统的 VSYNC 中断信号 。
它本质是一个 Java 类 , 如果直译的话为舞蹈指导 , 这是一个极富诗意的表达 , 看到这个词不得不赞叹设计者除了 Coding 之外的广泛视野 。
舞蹈是有节奏的 , 节奏使舞蹈的每个动作更加协调和连贯;视图刷新也是如此 。
Choreographer 可以接收系统的 VSYNC 信号 , 统一管理应用的输入、动画和绘制等任务的执行时机 。 Android 的 UI 绘制任务将在它的统一指挥下 , 井然有序的完成 。 业界一般通过它来监控应用的帧率 。
Choreographer 的构造方法:
private Choreographer(Looper looper, int vsyncSource) {// 当前线程的LoopermLooper = looper;// 创建该Looper的HandlermHandler = new FrameHandler(looper);// 是否开启VSYNC , 开启VSYNC后将通过FrameDisplayEventReceiver接受// VSYNC脉冲mDisplayEventReceiver = USE_VSYNC? new FrameDisplayEventReceiver(looper, vsyncSource): null;mLastFrameTimeNanos = Long.MIN_VALUE;// 计算一帧的时间// Android手机屏幕采用60Hz的刷新频率// 这里是纳秒 ≈16000000ns 还是16msmFrameIntervalNanos = (long)(1000000000 / getRefreshRate());// 创建一个CallbackQueu的数组 , 默认为4// CallbackQueue中存放要执行的输入、动画、遍历绘制等任务// 也就是 CALLBACK_INPUT、CALLBACK_ANIMATION、CALLBACK_TRAVERSALmCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];for (int i = 0; i <= CALLBACK_LAST; i++) {mCallbackQueues[i] = new CallbackQueue();}// b/68769804: For low FPS experiments.setFPSDivisor(SystemProperties.getInt(ThreadedRenderer.DEBUG_FPS_DIVISOR, 1));}Choreographer 是线程单例的 , 而且必须要和一个 Looper 绑定 , 因为其内部有一个 Handler 需要和当前绘制线程的 Looper 绑定 。DisplayEventReceiver 是一个 abstract class , 在其构造方法内会通过 JNI 创建一个 IDisplayEventConnection 的 VSYNC 的监听者 。
另外 DisplayEventReceiver 中包含两个非常重要的方法:一个用于需要绘制任务时 , 申请 VSYNC 信号的 scheduleVsync 方法 , 另一个用于接收 VSYNC 信号的 onVsync 方法 。 FrameDisplayEventReceiver 是 DisplayEventReceiver 的唯一实现类 , 并重写 onVsync 方法用于通知 Choreographer 。
推荐阅读
- 落叶知秋|中芯国际将被美国拉黑,鸿蒙系统已有进展,未来科技方向在何方?
- 落叶知秋|解析无源RFID与有源RFID在仓库管理各大优势
- 中式客厅该怎么挂画 一看就懂的5大实用布局原则
- 落叶知秋|揭秘,IT培训行业营销拓客秘籍
- 落叶知秋|科技强警||城中警方研发水下机器人亮相国内顶尖舞台
- 程序员|“对不起,我们不要IT培训班出来的程序员”!
- 小熊回收站|“对不起,我们不要IT培训班出来的程序员”
- 落叶知秋|用了一年的iPhone 8,现在的我终于要把它换掉了
- 小熊科技|程序员你是怎么绘制架构图?
- 程序员|程序员:代码全部替换成中文,你能接受吗?
