「这是我参与11月更文挑战的第11天,活动详情查看:2021最后一次更文挑战」
View调用requestLayout()发起UI重绘,new Runnable丢到Choreographer的消息队列,Choreographer向SurfaceFlinger取请求下一个Vsync信号,SurfaceFlinger在下一个Vsync信号来的时候会向Choreographer发送消息去处理消息队列中的任务。
1.初始化
在Activity的启动流程中,handleResumeActivity
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
wm.addView(decor, l);
} else {
a.onWindowAttributesChanged(l);
}
}
调用WindowManagerImpl的addView方法
mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,
mContext.getUserId());
mGlobal是WindowManagerGlobal的单例对象。
/frameworks/base/core/java/android/view/WindowManagerGlobal.java$addView
root = new ViewRootImpl(view.getContext(), display);
root是ViewRootImpl的实例对象,在ViewRootImpl的构造方法中会创建Choreographer的单例对象。
public ViewRootImpl(Context context, Display display, IWindowSession session,
boolean useSfChoreographer) {
//...
mChoreographer = useSfChoreographer
? Choreographer.getSfInstance() : Choreographer.getInstance();
//...
}
上面简述了Choreographer的初始化调用流程,紧接着继续介绍Choreographer的初始化。
public static Choreographer getInstance() {
return sThreadInstance.get();
}
2. Choreographer初始化
Choreographer 的单例初始化
private static final ThreadLocal<Choreographer> sThreadInstance =
new ThreadLocal<Choreographer>() {
@Override
protected Choreographer initialValue() {
Looper looper = Looper.myLooper();
if (looper == null) {
throw new IllegalStateException("The current thread must have a looper!");
}
//创建Choreographer对象
Choreographer choreographer = new Choreographer(looper, VSYNC_SOURCE_APP);
if (looper == Looper.getMainLooper()) {
mMainInstance = choreographer;
}
return choreographer;
}
};
在初始化过程前会创建ThreadLocal,从而保证Choreographer线程单例,一般是主线程。
Choreographer的很多任务调度是通过FrameHandler,因此器所在线程必须有Looper。
Choreographer构造方法:
private Choreographer(Looper looper, int vsyncSource) {
mLooper = looper;
// 1. 初始化FrameHandler
mHandler = new FrameHandler(looper);
// 2. 初始化 DisplayEventReceiver
mDisplayEventReceiver = USE_VSYNC
? new FrameDisplayEventReceiver(looper, vsyncSource)
: null;
//上一帧绘制 的时间点
mLastFrameTimeNanos = Long.MIN_VALUE;
//每一帧的间隔,16.6ms
mFrameIntervalNanos = (long) (1000000000 / getRefreshRate());
//3. 初始化 CallbacksQueues
mCallbackQueues = 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));
}
在初始化的过程中主要做了三件事:
- 初始化FrameHandler,绑定Looper响应时间。
- 初始化FrameDisplayEventReceiver,与SurfaceFlinger响应调度Vsync。
- 初始化CallbacksQueues,任务调度的回调都是放到这里。
FrameHandler
FrameHandler执行了核心方法doFrame()和调度Vsync,具体方法描述请参考注释。
private final class FrameHandler extends Handler {
public FrameHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_DO_FRAME://开始渲染下一帧的操作
doFrame(System.nanoTime(), 0);
break;
case MSG_DO_SCHEDULE_VSYNC://请求 Vsync
doScheduleVsync();
break;
case MSG_DO_SCHEDULE_CALLBACK://处理 Callback
doScheduleCallback(msg.arg1);
break;
}
}
}
FrameDisplayEventReceiver
请求返回Vsync信号后,会回调onVsync方法 这里面有三个重要方法:
- onVsync():响应 Vsync 信号
- scheduleVsync():调度 Vsync 信号
- run():执行 doFrame(),doFrame() 内部会做计算掉帧、响应 Input、Animation、Traversal(measure/layout/draw)、Commit
private final class FrameDisplayEventReceiver extends DisplayEventReceiver
implements Runnable {
private boolean mHavePendingVsync;
private long mTimestampNanos;
private int mFrame;
public FrameDisplayEventReceiver(Looper looper, int vsyncSource) {
super(looper, vsyncSource, CONFIG_CHANGED_EVENT_SUPPRESS);
}
@Override
// Vsync信号的回调
public void onVsync(long timestampNanos, long physicalDisplayId, int frame) {
long now = System.nanoTime();
if (timestampNanos > now) {
Log.w(TAG, "Frame time is " + ((timestampNanos - now) * 0.000001f)
+ " ms in the future! Check that graphics HAL is generating vsync "
+ "timestamps using the correct timebase.");
timestampNanos = now;
}
if (mHavePendingVsync) {
Log.w(TAG, "Already have a pending vsync event. There should only be "
+ "one at a time.");
} else {
mHavePendingVsync = true;
}
mTimestampNanos = timestampNanos;
mFrame = frame;
Message msg = Message.obtain(mHandler, this); //public void run()
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
}
//执行doFrame
@Override
public void run() {
mHavePendingVsync = false;
doFrame(mTimestampNanos, mFrame);
}
}