一、概述
前面介绍了屏幕刷新机制中的view绘制原理,涉及到的Choreographer并没有深入其里面具体的操作,这一篇讲详细介绍Choreographer。Choreographer翻译成中文是编舞者的意思,在Android系统4.1开始加入这个类,主要来控制同步处理输入(input),动画(animation),绘制(draw),在UI显示的时候每一帧完成的只有这三种。在这个类的前面有一行注释,大概意思就是要协调控制三个UI操作的时序,这也和其编舞者名称相符合。
1 | /** |
在类中有四种任务队列,当收到Vsync信号时会执行这四种任务队列里面的任务
private final CallbackQueue[] mCallbackQueues;
1 | void doFrame(long frameTimeNanos, int frame) { |
CALLBACK_INPUTL:输入
CALLBACK_ANIMATION:动画
CALLBACK_TRAVERSAL:绘制,执行measure,layout,draw
CALLBACK_COMMIT:绘制完成的提交操作,用来修正动画的启动时间。这里主要是为了解决ValueAnimator问题而引入的,因为遍历时间过长导致动画时间启动过长,时间缩短,导致跳帧,这里修改动画第一个frame开始时间延后。
1 | // Update the frame time if necessary when committing the frame. |
二、Choreographer启动流程
在前面介绍的view绘制原理的流程中,在WMG.addView会对ViewRootImpl进行初始化操作
2.1 创建ViewRootImpl
[->ViewRootImpl.java]
1 | public ViewRootImpl(Context context, Display display) { |
2.2 创建Choreographer
[->Choreographer.java]
1 | public static Choreographer getInstance() { |
[->Choreographer.java]
1 | // Thread local storage for the choreographer. |
当前线程所在的为主线程(UI线程),可以看到每个线程都有一个Choreographer
[->Choreographer.java]
1 | private Choreographer(Looper looper, int vsyncSource) { |
mLastFrameTimeNanos:上一次帧绘制的时间点
mFrameIntervalNanos,帧间时长一般等于16.7ms
2.3 初始化FrameHandler
[->Choreographer.java]
1 | private final class FrameHandler extends Handler { |
2.4 创建FrameDisplayEventReceiver
[->Choreographer.java]
1 | private final class FrameDisplayEventReceiver extends DisplayEventReceiver |
2.4.1 DisplayEventReceiver
[->DisplayEventReceiver.java]
1 | public DisplayEventReceiver(Looper looper) { |
2.4.2 nativeInit
[->/core/jni/android_view_DisplayEventReceiver.cpp]
1 | static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak, |
2.4.3 NativeDisplayEventReceiver
[->/core/jni/android_view_DisplayEventReceiver.cpp]
1 | NativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env, |
DisplayEventDispatcher继承于LooperCallback,mReceiverWeakGlobal记录java层DisplayEventReceiver对象的全局引用。
2.4.4 initialize
[->libs/androidfw/DisplayEventDispatcher.cpp]
1 | status_t DisplayEventDispatcher::initialize() { |
监听mReceiver所获取文件句柄,一旦有数据到来,则回调this,所复写LooperCallback对象的handleEvent方法
2.4.5 addFd
[->system/core/libutils/Looper.cpp]
1 | int Looper::addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data) { |
2.4.6 handleEvent
[->system/core/libutils/Looper.cpp]
1 | int Looper::pollInner(int timeoutMillis) { |
三、Vsync信号回调流程
当Vsync信号来时,经过层层调用后会执行handleEvent方法,详细流程会在SurfaceFlinger中介绍。
3.1 handleEvent
[->libs/androidfw/DisplayEventDispatcher.cpp]
1 | int DisplayEventDispatcher::handleEvent(int, int events, void*) { |
3.1.1 processPendingEvents
[->libs/androidfw/DisplayEventDispatcher.cpp]
1 | bool DisplayEventDispatcher::processPendingEvents( |
遍历所有的事件,当有多个Vsync事件来时,则只关注最近一次的事件
3.1.2 dispatchVsync(C++)
[->core/jni/android_view_DisplayEventReceiver.cpp]
1 | void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t count) { |
3.2 dispatchVsync(Java)
[->DisplayEventReceiver.java]
1 | // Called from native code. |
之后的流程参考View的绘制原理。
四、总结
这里主要介绍了Choreographer的启动流程以及其回调的流程。
1.Choreographer主要来控制同步处理输入(input),动画(animation),绘制(draw);
2.通过监听mReceiver所获取文件句柄,来获取回调;
3.可以通过Choreographer getInstance().postFrameCallback来监听帧率。