public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
//1 检测线程checkThread();
mLayoutRequested = true;
//2 scheduleTraversals();
}
}
注释1 是检测当前是不是在主线程
2.1 ViewRootImpl#checkThread
voidcheckThread() {
if (mThread != Thread.currentThread()) {
thrownew CalledFromWrongThreadException(
"Only the original thread that created a view hierarchy can touch its views.");
}
}
Message next() {
...
for (;;) {
...
synchronized (this) {
// Try to retrieve the next message. Return if found.
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) { //如果msg不为空并且target为空
// Stalled by a barrier. Find the next asynchronous message in the queue.
do {
prevMsg = msg;msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
...
}
// Enable/disable vsync for animations and drawing. 系统属性参数,默认trueprivatestaticfinalbooleanUSE_VSYNC= SystemProperties.getBoolean(
"debug.choreographer.vsync", true);
...
privatevoidscheduleFrameLocked(long now) {
//标志位,避免不必要的多次调用if (!mFrameScheduled) {
mFrameScheduled = true;
if (USE_VSYNC) {
if (DEBUG_FRAMES) {
Log.d(TAG, "Scheduling next frame on vsync.");
}
// If running on the Looper thread, then schedule the vsync immediately,// otherwise post a message to schedule the vsync from the UI thread// as soon as possible.//1 如果当前线程是UI线程,直接执行scheduleFrameLocked,否则通过Handler处理if (isRunningOnLooperThreadLocked()) {
scheduleVsyncLocked();
} else {
Messagemsg= mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC);
msg.setAsynchronous(true);
mHandler.sendMessageAtFrontOfQueue(msg);
}
} else {
finallongnextFrameTime= Math.max(
mLastFrameTimeNanos / TimeUtils.NANOS_PER_MS + sFrameDelay, now);
if (DEBUG_FRAMES) {
Log.d(TAG, "Scheduling next frame in " + (nextFrameTime - now) + " ms.");
}
Messagemsg= mHandler.obtainMessage(MSG_DO_FRAME);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, nextFrameTime);
}
}
}
/** * Schedules a single vertical sync pulse to be delivered when the next * display frame begins. */publicvoidscheduleVsync() {
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); //1、请求vsync
}
}
// Called from native code. //2、vsync来的时候底层会通过JNI回调这个方法
@SuppressWarnings("unused")
privatevoiddispatchVsync(long timestampNanos, int builtInDisplayId, int frame) {
onVsync(timestampNanos, builtInDisplayId, frame);
}
/** * Called when a vertical sync pulse is received. * The recipient should render a frame and then call {@link #scheduleVsync} * to schedule the next vertical sync pulse. * * @param timestampNanos The timestamp of the pulse, in the {@link System#nanoTime()} * timebase. * @param builtInDisplayId The surface flinger built-in display id such as * {@link SurfaceControl#BUILT_IN_DISPLAY_ID_MAIN}. * @param frame The frame number. Increases by one for each vertical sync interval. */publicvoidonVsync(long timestampNanos, int builtInDisplayId, int frame) {
}
privatefinalclassFrameDisplayEventReceiverextendsDisplayEventReceiverimplementsRunnable {
privateboolean mHavePendingVsync;
privatelong mTimestampNanos;
privateint mFrame;
publicFrameDisplayEventReceiver(Looper looper) {
super(looper);
}
@OverridepublicvoidonVsync(long timestampNanos, int builtInDisplayId, int frame) {
// Post the vsync event to the Handler.// The idea is to prevent incoming vsync events from completely starving// the message queue. If there are no messages in the queue with timestamps// earlier than the frame time, then the vsync event will be processed immediately.// Otherwise, messages that predate the vsync event will be handled first.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;
}
mTimestampNanos = timestampNanos;
mFrame = frame;
Messagemsg= Message.obtain(mHandler, this); //1 callback是this,会回调run方法
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
}
@Overridepublicvoidrun() {
mHavePendingVsync = false;
doFrame(mTimestampNanos, mFrame); //2
}
}
void doFrame(long frameTimeNanos, int frame) {
final long startNanos;
synchronized (mLock) {
...
long intendedFrameTimeNanos = frameTimeNanos;startNanos = System.nanoTime();
// 1 当前时间戳减去vsync来的时间,也就是主线程的耗时时间
final long jitterNanos = startNanos - frameTimeNanos;
if (jitterNanos >= mFrameIntervalNanos) {
//1帧是16毫秒,计算当前跳过了多少帧,比如超时162毫秒,那么就是跳过了10帧
final long skippedFrames = jitterNanos / mFrameIntervalNanos;
// SKIPPED_FRAME_WARNING_LIMIT 默认是30,超时了30帧以上,那么就log提示
if (skippedFrames >= SKIPPED_FRAME_WARNING_LIMIT) {
Log.i(TAG, "Skipped " + skippedFrames + " frames! "
+ "The application may be doing too much work on its main thread.");
}
// 取余,计算离上一帧多久了,一帧是16毫秒,所以lastFrameOffset 在0-15毫秒之间,这里单位是纳秒
final long lastFrameOffset = jitterNanos % mFrameIntervalNanos;
if (DEBUG_JANK) {
Log.d(TAG, "Missed vsync by " + (jitterNanos * 0.000001f) + " ms "
+ "which is more than the 8frame interval of "
+ (mFrameIntervalNanos * 0.000001f) + " ms! "
+ "Skipping " + skippedFrames + " frames and setting frame "
+ "time to " + (lastFrameOffset * 0.000001f) + " ms in the past.");
}
// 出现掉帧,把时间修正一下,对比的是上一帧时间
frameTimeNanos = startNanos - lastFrameOffset;
}
//2、时间倒退了,可能是由于改了系统时间,此时就重新申请vsync信号(一般不会走这里)
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;
}
mFrameInfo.setVsync(intendedFrameTimeNanos, frameTimeNanos);mFrameScheduled = false;mLastFrameTimeNanos = frameTimeNanos;
}
//3 能绘制的话,就走到下面
try {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Choreographer#doFrame");
AnimationUtils.lockAnimationClock(frameTimeNanos / TimeUtils.NANOS_PER_MS);
mFrameInfo.markInputHandlingStart();
doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
mFrameInfo.markAnimationsStart();
doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
mFrameInfo.markPerformTraversalsStart();
doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);
}
}
publicstaticvoidloop() {
...
for (;;) {
...
// This must be in a local variable, in case a UI event sets the loggerfinalPrinterlogging= me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}