mFrame = frame;
Message msg = Message.obtain(mHandler, this);
msg.setAsynchronous(true);//Message设置为异步
mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
}
@Override
public void run() {
mHavePendingVsync = false;
doFrame(mTimestampNanos, mFrame);
}
}
接收到垂直同步信号后回调onVsync方法,这个方法使用handler发送带callback(Runnable类型,自身已继承)的message,最后run()中也是调用doFrame();(关于这个handler的这个操作详细信息逻辑,参照下面本文附录一 handler 分发message
这个message设置为了异步 (msg.setAsynchronous(true);)这意味这他有优先执行的权利,他是怎么被优先执行的呢?参照附录三 message的异步模式
综上,添加callback流程
二、执行
doFrame
void doFrame(long frameTimeNanos, int frame) {
final long startNanos;
synchronized (mLock) {
if (!mFrameScheduled) {
return; // no work to do
}
//当前时间
startNanos = System.nanoTime();
//当前时间和垂直同步时间
final long jitterNanos = startNanos - frameTimeNanos;
//垂直同步时间和当前时间的差值如果大于一个周期就修正一下
if (jitterNanos >= mFrameIntervalNanos) {
//取插值和始终周期的余数
final long lastFrameOffset = jitterNanos % mFrameIntervalNanos;
//当前时间减去上一步得到的余数当作最新的始终信号时间
frameTimeNanos = startNanos - lastFrameOffset;
}
//垂直同步时间上一次时间还小,就安排下次垂直,直接返回
if (frameTimeNanos < mLastFrameTimeNanos) {
scheduleVsyncLocked();
return;
}
mFrameInfo.setVsync(intendedFrameTimeNanos, frameTimeNanos);
mFrameScheduled = false;
mLastFrameTimeNanos = frameTimeNanos;
}
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);
} finally {
AnimationUtils.unlockAnimationClock();
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
if (DEBUG_FRAMES) {
final long endNanos = System.nanoTime();
Log.d(TAG, "Frame " + frame + ": Finished, took "
- (endNanos - startNanos) * 0.000001f + " ms, latency "
- (startNanos - frameTimeNanos) * 0.000001f + " ms.");
}
}
- 第一步修正判断
-
当前时间 startNanos = System.nanoTime();
-
求当前时间和垂直同步时间的差值 :jitterNanos = startNanos - frameTimeNanos;
-
垂直同步时间和当前时间的差值如果大于一个周期(jitterNanos >= mFrameIntervalNanos)就修正一下
-
取插值和始终周期的余数:lastFrameOffset = jitterNanos % mFrameIntervalNanos;
-
当前时间减去上一步得到的余数当作最新的始终信号时间:frameTimeNanos = startNanos - lastFrameOffset;
-
垂直同步时间上一次时间还小,就安排下次渲染: frameTimeNanos < mLastFrameTimeNanos,直接返回
- 第二步执行callback callback的执行顺序是:
- CALLBACK_INPUT输入时间优先级最高
- CALLBACK_ANIMATION 动画的次之
- CALLBACK_TRAVERSAL UI绘制布局的再次之
- CALLBACK_COMMIT动画修正相关最后。
2.2 doCallbacks();
- 在 CallbackQueue[] mCallbackQueues在取特定类型(输入,动画,布局,Commit)的单向链表
- 然后取出已到期的Callback/Runable执行
取出需要被执行的Actions
Action包装在CallbackRecord中,是一个单向列表,按照时间的大小顺序排列的。 取出待执行的Actions是通过CallBackQueue的extractDueCallbacksLocked()方法,可以把CallBackQueue看做是CallBack的管理类,其中还包括添加Action addCallbackLocked(),移除Action removeCallbacksLocked(),是否有带起的Anction hasDueCallbacksLocked()方法。
private final class CallbackQueue {
//链表头
private CallbackRecord mHead;
//是否存在已经到期的Action
public boolean hasDueCallbacksLocked(long now) {
return mHead != null && mHead.dueTime <= now;
}
//获取已经到期的Action
public CallbackRecord extractDueCallbacksLocked(long now) {
…
return callbacks;
}
//添加Action
public void addCallbackLocked(long dueTime, Object action, Object token) {
…
}
//移除Action
public void removeCallbacksLocked(Object action, Object token) {
…
}
}
执行Action
for (CallbackRecord c = callbacks; c != null; c = c.next) {
c.run(frameTimeNanos);
}
从callback中遍历出CallBcakRecord,挨个执行。
三、小结
- Choreographer对外提供了postCallback等方法,最终他们内部都是通过调用postCallbackDelayedInternal()实现这个方法主要会做两件事情
- 存储Act
ion - 请求垂直同步,垂直同步
- 垂直同步回调立马执行Action(CallBack/Runnable)。
- Action一个动作内容的类型可能是
- CALLBACK_INPUT输入时间优先级最高
- CALLBACK_ANIMATION 动画的次之
- CALLBACK_TRAVERSAL UI绘制布局的再次之
- CALLBACK_COMMIT动画修正相关最后。
- 复习Hanlder机制,我认为他是Android系统跑起来的大引擎终点关注下,handler对message的分发执行,以及“异步模式”。
附
附一、关于handler执行Message
下面是handler分发逻辑,Looper在MessageQueue得到要执行的message之后就会交给message的target(Handler类型)属性处理msg.target.dispatchMessage(msg);;
public void dispatchMessage(Message msg) {
//当msg的callback不为空的时候直接执行msg的callback它是一个Runnable对象
if (msg.callback != null) {
handleCallback(msg);
} else {
//然后再交给mCallBack,它是handler的一个属性,
//创建Handler的时候可以选择传入一个CallBack对象
//当callBack中handleMessage返回true的时候表示:True if no further handling is desired(不需要进一步处理)
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
//当mCallback处理返回为false的时候才去执行Handler自身的handleMessage()方法
handleMessage(msg);
}
}
关键逻辑在已注释,小结一下 handler的执行分发Message逻辑
- 如果message的callback(runnable)属性不为空,调用这个runable的run()方法执行
private static void handleCallback(Message message) {
message.callback.run();
}
当我们使用handler.post(Runnable r)方法时候就是将r设置给message的callback
- 上述条件不满足的情况下,如果handler自身的mCallback不为空的时候就会,将message交给mCallback处理,handlerMessage()结束。这个属性是在handler创建的时候传入的。mCallback是CallBack类型,他是handler的一个内部接口。
public interface Callback {
boolean handleMessage(Message msg);
}
3.当messaga 的callBak为空,且handler的mCallBack为空的时候就交给自己的handlerMessage()方法执行了。我们在自定义handler的时候可以重写这个方法对message进行相应的操作。
附二 、mFrameScheduled属性作用
- 执行callcack的时候会判断mFrameScheduled属性如果为false表示没有安排渲染下一帧就直接返回,不执行。
void doFrame(long frameTimeNanos, int frame) {
final long startNanos;
synchronized (mLock) {
if (!mFrameScheduled) {
return; // no work to do
}
…
…
mFrameScheduled = false;
…
}
- 在scheduleFrameLocked()方法中,将mFrameScheduled值设置为ture表示安排了请求渲染下一帧。如果这时mFrameScheduled为true表示已经安排了下一帧那么就返回,不添乱!
附三、Handler机制的异步模式
作用
“异步模式”的作用就是优先,asynchronous 的message在异步模式下有优先执行的权。
用法
MessageQueue使用postSyncBarrier()方法添加屏障,removeSyncBarrier()方法移除屏障这个两个方法是成对使用的。
实现原理
- messageQueued的postSyncBarrier方法向messagequeue的头部添加一个target属性为null的message
- messageQueue的next()当碰到target为null的message的时候就只会在message链表中取出去“异步message”,而忽略普通的message,交给Looper做进一步分发处理。
Message next() {
…
for (;