文章目录
- 引言
- 一、Choreographer 信号的分发处理
- 二、Choreographer.FrameDisplayEventReceiver # onVsync方法向主线程发送Message消息
- 三、主线程Looper处理消息并触发Choreographer.FrameDisplayEventReceiver.run方法
- 四、Choreographer#doFrame处理回调
- 1、Choreographer#doFrame方法处理VSync消息执行四种回调事件
- 2、Choreographer#doCallbacks方法处理四种回调事件
- 3、CallbackRecord #run方法响应VSync信号
- 五、Choreographer#postFrameCallback()
引言
前一篇文章 Android 进阶——图形显示系统之VSync和 Choreographer的创建详解(一)介绍了关于Android VSync信号产生和基本管理以及Choreographer创建的过程,由于篇幅问题,把应用进程接到VSync 信号后如何处理留到了本篇文章,如果还没有阅读过上一篇建议先去阅读,系列文章:
- Android 进阶——图形显示系统之VSync和 Choreographer的创建详解(一)
- Android 进阶——图形显示系统之Choreographer监听VSync并提供回调接口详解(二)
一、Choreographer 信号的分发处理
书接上文Choreographer 在创建的过程不仅仅是完成自身对象的创建(一个线程拥有自己独立的副本)更重要的是完成了一个VSync 监听处理模型的初始化,还是从上篇的接到VSync信号后就会回调Java层DisplayEventReceiver#onVsync方法
// Called from native code.@SuppressWarnings("unused")private void dispatchVsync(long timestampNanos, int builtInDisplayId, int frame) {onVsync(timestampNanos, builtInDisplayId, frame);}
二、Choreographer.FrameDisplayEventReceiver # onVsync方法向主线程发送Message消息
@Overridepublic void onVsync(long timestampNanos, int builtInDisplayId, int frame) {//是否支持处理副屏的VSync信号if (builtInDisplayId != SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {Log.d(TAG, "Received vsync from secondary display, but we don't support "+ "this case yet. Choreographer needs a way to explicitly request "+ "vsync for a specific display to ensure it doesn't lose track "+ "of its scheduled vsync.");scheduleVsync();return;}// Post the vsync event to the Handler.long now = System.nanoTime();mTimestampNanos = timestampNanos;mFrame = frame;//传给Message的Callback 对象为FrameDisplayEventReceiver自身并发送异步消息,即本身作为runnable传入msg, 发消息后会走run(),即doFrame(),也是异步消息Message msg = Message.obtain(mHandler, this);msg.setAsynchronous(true);//@link Choreographer 构造函数初始化的全局FrameHandler对象mHandlermHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);}
即onVsync()过程是通过FrameHandler向主线程Looper发送了一个自带Callback(即FrameDisplayEventReceiver)的消息,
三、主线程Looper处理消息并触发Choreographer.FrameDisplayEventReceiver.run方法
又FrameDisplayEventReceiver实现了Runnable接口,当主线程Looper执行到该消息时,则调用FrameDisplayEventReceiver.run()方法。