前言今天继续屏幕刷新机制的知识讲解,上文说到 代码未动,图先行UI变化上期说到app并不是每一个 那我们就从有绘制需求开始看,当我们修改了UI后,都会执行 可以看到,最后会调用到父布局 public ViewRootImpl(Context context, Display display) { //... mChoreographer = Choreographer.getInstance(); } void scheduleTraversals() { if (!mTraversalScheduled) { mTraversalScheduled = true; mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier(); mChoreographer.postCallback( Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null); //... } } 为了方便查看,我只留了相关代码。可以看到,在 Choreographer实例化//Choreographer.java public static Choreographer getInstance() { return sThreadInstance.get(); } private static final ThreadLocal<Choreographer> sThreadInstance = new ThreadLocal<Choreographer>() { @Override protected Choreographer initialValue() { Looper looper = Looper.myLooper(); //... Choreographer choreographer = new Choreographer(looper, VSYNC_SOURCE_APP); //... return choreographer; } }; private Choreographer(Looper looper, int vsyncSource) { mLooper = looper; mHandler = new FrameHandler(looper); //初始化FrameDisplayEventReceiver mDisplayEventReceiver = USE_VSYNC ? new FrameDisplayEventReceiver(looper, vsyncSource) : null; mLastFrameTimeNanos = Long.MIN_VALUE; //一帧间隔时间 mFrameIntervalNanos = (long)(1000000000 / getRefreshRate()); mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1]; for (int i = 0; i <= CALLBACK_LAST; i++) { mCallbackQueues[i] = new CallbackQueue(); } } ThreadLocal,是不是有点熟悉?之前说Handler的时候说过,Handler是怎么获取当前线程的Looper的?就是通过这个 存储方法还是一样,以 所以这里创建的mHandler就是 postCallbackprivate void postCallbackDelayedInternal(int callbackType, Object action, Object token, long delayMillis) { if (DEBUG_FRAMES) { Log.d(TAG, "PostCallback: type=" + callbackType + ", action=" + action + ", token=" + token + ", delayMillis=" + delayMillis); } synchronized (mLock) { final long now = SystemClock.uptimeMillis(); final long dueTime = now + delayMillis; mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token); if (dueTime <= now) { scheduleFrameLocked(now); } else { Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action); msg.arg1 = callbackType; msg.setAsynchronous(true); mHandler.sendMessageAtTime(msg, dueTime); } } } 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: doScheduleVsync(); break; case MSG_DO_SCHEDULE_CALLBACK: doScheduleCallback(msg.arg1); break; } } } void doScheduleCallback(int callbackType) { synchronized (mLock) { if (!mFrameScheduled) { final long now = SystemClock.uptimeMillis(); if (mCallbackQueues[callbackType].hasDueCallbacksLocked(now)) { scheduleFrameLocked(now); } } } } 在 然后判断设定的时间是否在当前时间之后,也就是有没有延迟,如果有延迟就发送延迟消息消息 scheduleFrameLocked(准备申请VSYNC信号)private void scheduleFrameLocked(long now) { if (!mFrameScheduled) { mFrameScheduled = true; if (USE_VSYNC) { //是否运行在主线程 if (isRunningOnLooperThreadLocked()) { scheduleVsyncLocked(); } else { //通过Handler切换线程 Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC); msg.setAsynchronous(true); mHandler.sendMessageAtFrontOfQueue(msg); } } else { //计算下一帧的时间 final long nextFrameTime = Math.max( mLastFrameTimeNanos / TimeUtils.NANOS_PER_MS + sFrameDelay, now); Message msg = mHandler.obtainMessage(MSG_DO_FRAME); msg.setAsynchronous(true); mHandler.sendMessageAtTime(msg, nextFrameTime); } } } case MSG_DO_FRAME: doFrame(System.nanoTime(), 0); break; case MSG_DO_SCHEDULE_VSYNC: doScheduleVsync(); break; void doScheduleVsync() { synchronized (mLock) { if (mFrameScheduled) { scheduleVsyncLocked(); } } } 该方法中,首先判断了是否开启了 如果没有开启 另外可以看到,刚才我们用到Handler发送消息的时候,都调用了 小结1通过上面一系列方法,我们能得到一个初步的逻辑过程了:
在这个过程中, 继续看 scheduleVsyncLockedprivate void scheduleVsyncLocked() { mDisplayEventReceiver.scheduleVsync(); } public void scheduleVsync() { if (mReceiverPtr == 0) { Log.w(TAG, "Attempted to schedule a vertical sync pulse but the display event " + "receiver has already been disposed."); } else { nativeScheduleVsync(mReceiverPtr); } } 代码很简单,就是通过 这个 刚才说到调用 onVsync(接收VSYNC信号)private final class FrameDisplayEventReceiver extends DisplayEventReceiver implements Runnable { @Override public void onVsync(long timestampNanos, long physicalDisplayId, int frame) { //... mTimestampNanos = timestampNanos; mFrame = frame; Message msg = Message.obtain(mHandler, this); msg.setAsynchronous(true); mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS); } @Override public void run() { mHavePendingVsync = false; doFrame(mTimestampNanos, mFrame); } } 这里同样通过Handler发送了一条消息,执行了本身的 doFrame(绘制帧数据)void doFrame(long frameTimeNanos, int frame) { final long startNanos; synchronized (mLock) { //... //当前帧的vsync信号来的时间,假如为12分200ms long intendedFrameTimeNanos = frameTimeNanos; //当前时间,也就是开始绘制的时间,假如为12分150ms startNanos = System.nanoTime(); //计算时间差,如果大于一个帧时间,则是跳帧了。比如是50ms,大于16ms final long jitterNanos = startNanos - frameTimeNanos; if (jitterNanos >= mFrameIntervalNanos) { //计算掉了几帧,50/16=3帧 final long skippedFrames = jitterNanos / mFrameIntervalNanos; //计算一帧内时间差,50%16=2ms final long lastFrameOffset = jitterNanos % mFrameIntervalNanos; //修正时间,vsync信号应该来得时间,为12分148ms,保证和绘制时间对应上 frameTimeNanos = startNanos - lastFrameOffset; } if (frameTimeNanos < mLastFrameTimeNanos) { //信号时间已过,不能再绘制了,等待下一个vsync信号,保证后续时间同步上 scheduleVsyncLocked(); return; } mFrameScheduled = false; mLastFrameTimeNanos = frameTimeNanos; } try { //执行相关的callback任务 mFrameInfo.markInputHandlingStart(); doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos); mFrameInfo.markAnimationsStart(); doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos); doCallbacks(Choreographer.CALLBACK_INSETS_ANIMATION, frameTimeNanos); mFrameInfo.markPerformTraversalsStart(); doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos); doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos); } finally { AnimationUtils.unlockAnimationClock(); Trace.traceEnd(Trace.TRACE_TAG_VIEW); } } 这里主要的工作就是:
doCallbacks(执行任务)void doCallbacks(int callbackType, long frameTimeNanos) { CallbackRecord callbacks; synchronized (mLock) { final long now = System.nanoTime(); callbacks = mCallbackQueues[callbackType].extractDueCallbacksLocked( now / TimeUtils.NANOS_PER_MS); if (callbacks == null) { return; } mCallbacksRunning = true; if (callbackType == Choreographer.CALLBACK_COMMIT) { final long jitterNanos = now - frameTimeNanos; Trace.traceCounter(Trace.TRACE_TAG_VIEW, "jitterNanos", (int) jitterNanos); if (jitterNanos >= 2 * mFrameIntervalNanos) { final long lastFrameOffset = jitterNanos % mFrameIntervalNanos + mFrameIntervalNanos; frameTimeNanos = now - lastFrameOffset; mLastFrameTimeNanos = frameTimeNanos; } } } try { Trace.traceBegin(Trace.TRACE_TAG_VIEW, CALLBACK_TRACE_TITLES[callbackType]); for (CallbackRecord c = callbacks; c != null; c = c.next) { c.run(frameTimeNanos); } } finally { synchronized (mLock) { mCallbacksRunning = false; do { final CallbackRecord next = callbacks.next; recycleCallbackLocked(callbacks); callbacks = next; } while (callbacks != null); } Trace.traceEnd(Trace.TRACE_TAG_VIEW); } } private static final class CallbackRecord { public CallbackRecord next; public long dueTime; public Object action; // Runnable or FrameCallback public Object token; @UnsupportedAppUsage public void run(long frameTimeNanos) { if (token == FRAME_CALLBACK_TOKEN) { ((FrameCallback)action).doFrame(frameTimeNanos); } else { ((Runnable)action).run(); } } } 其实就是按类型,从 而这个run方法中,判断了token,并执行了 mChoreographer.postCallback( Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null); token为空,所以会执行到action也就是 所以兜兜转转,又回到了 最后看看 mTraversalRunnablefinal class TraversalRunnable implements Runnable { @Override public void run() { doTraversal(); } } void doTraversal() { if (mTraversalScheduled) { mTraversalScheduled = false; mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier); if (mProfile) { Debug.startMethodTracing("ViewAncestor"); } performTraversals(); if (mProfile) { Debug.stopMethodTracing(); mProfile = false; } } } 这就很熟悉了吧,调用了 总结最后再看看总结图: 参考https:///post/6863756420380196877 拜拜 |
|