//looper 此时也是主线程 publicFrameDisplayEventReceiver(Looper looper, int vsyncSource) { super(looper, vsyncSource); }
//系统 native 方法会调用此方法 @Override publicvoidonVsync(long timestampNanos, int builtInDisplayId, int frame) { //判断是否是主显示屏幕 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; } //修正时间确保时间顺序正确 longnow= 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; }
//方法内有省略 voiddoFrame(long frameTimeNanos, int frame) { finallong startNanos; synchronized (mLock) { if (!mFrameScheduled) { return; //如果为渲染完成,则直接返回,这样就渲染不了当前帧 } //原来帧的绘制时间点 longintendedFrameTimeNanos= frameTimeNanos; startNanos = System.nanoTime(); finallongjitterNanos= startNanos - frameTimeNanos; if (jitterNanos >= mFrameIntervalNanos) { finallongskippedFrames= jitterNanos / mFrameIntervalNanos; //SKIPPED_FRAME_WARNING_LIMIT=30 如果页面复杂时,我们经常会看到 Log 里输出下面的信息,也就是说官方认为掉帧数=30时就认为太卡,建议优化了 if (skippedFrames >= SKIPPED_FRAME_WARNING_LIMIT) { Log.i(TAG, "Skipped " + skippedFrames + " frames! " + "The application may be doing too much work on its main thread."); } finallonglastFrameOffset= jitterNanos % mFrameIntervalNanos; if (DEBUG_JANK) { Log.d(TAG, "Missed vsync by " + (jitterNanos * 0.000001f) + " ms " + "which is more than the frame interval of " + (mFrameIntervalNanos * 0.000001f) + " ms! " + "Skipping " + skippedFrames + " frames and setting frame " + "time to " + (lastFrameOffset * 0.000001f) + " ms in the past."); } frameTimeNanos = startNanos - lastFrameOffset; }
if (frameTimeNanos < mLastFrameTimeNanos) { if (DEBUG_JANK) { Log.d(TAG, "Frame time appears to be going backwards. May be due to a " + "previously skipped frame. Waiting for next vsync."); } //请求 VSYNC scheduleVsyncLocked(); return; }
publicvoidscheduleVsync() { if (mReceiverPtr == 0) { Log.w(TAG, "Attempted to schedule a vertical sync pulse but the display event " + "receiver has already been disposed."); } else { //调用了 Native 方法 nativeScheduleVsync(mReceiverPtr); } }
通过查看源码知道整个屏幕刷新机制,平时看到 Log 里打印The application may be doing too much work on its main thread也知道了出处.也知道了经常使用的 requestLayout 其实最终其实执行的是 ViewRootImpl 的 TraversalRunnable,对于卡顿的形成也稍微有点了解.