首页 / 操作系统 / Linux / Android的postOnAnimation分析
在Android中绘图中,线程可以使用postOnAnimation函数,用于在系统进行下一次动画操作时,运行当前的线程,postOnAnimation(this): public void postOnAnimation(Runnable action) { final AttachInfo attachInfo = mAttachInfo; if (attachInfo != null) { attachInfo.mViewRootImpl.mChoreographer.postCallback( Choreographer.CALLBACK_ANIMATION, action, null); } else { // Assume that post will succeed later ViewRootImpl.getRunQueue().post(action); } } 只看attachInfo不为空的情况,会执行if里面的语句,可以看到属性的Choreographer,看一下Choreographer的postCallback: public void postCallback(int callbackType, Runnable action, Object token) { postCallbackDelayed(callbackType, action, token, 0); } postCallbackDelayed: public void postCallbackDelayed(int callbackType, Runnable action, Object token, long delayMillis) { if (action == null) { throw new IllegalArgumentException("action must not be null"); } if (callbackType < 0 || callbackType > CALLBACK_LAST) { throw new IllegalArgumentException("callbackType is invalid"); } postCallbackDelayedInternal(callbackType, action, token, delayMillis); } 可见最终的实现是在postCallbackDelayedInternal里面,看一下postCallbackDelayedInternal的代码: private void postCallbackDelayedInternal(int callbackType, Object action, Object token, long delayMillis) { if (DEBUG) { Xlog.d(TAG, "PostCallback: type=" + callbackType + ", action=" + action + ", token=" + token + ", delayMillis=" + delayMillis + ",this = " + this); } 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); } } } 可以看到在postCallbackDelayedInternal里,在mCallbackQueues队列里面的callbackType添加一个元素。mCallbackQueues是一个CallbackQueue,从命名里就可以看出现,是一个用于回调的队列,并且是安时间先后顺序排好的,与闹钟原理一样,并且里面有一个CallbackRecord类,记录回调相关的信息。callbackType的类型有三种:CALLBACK_INPUT、CALLBACK_ANIMATION、CALLBACK_TRAVERSAL,这里我们用的是CALLBACK_ANIMATION。在postOnAnimation没有delay,所以只要收到Vsync信号,便立即会被执行 。当有Vsync到来是,会执行doFrame,doFrame里有: ... doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos); doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos); doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos); doCallbacks里面有如下语句: ... callbacks = mCallbackQueues[callbackType].extractDueCallbacksLocked(now); ... try { for (CallbackRecord c = callbacks; c != null; c = c.next) { if (DEBUG) { Xlog.d(TAG, "RunCallback: type=" + callbackType + ", action=" + c.action + ", token=" + c.token + ", latencyMillis=" + (SystemClock.uptimeMillis() - c.dueTime) + ",this = " + this); } c.run(frameTimeNanos); } } finally { ... doCallbacks遍历postCallbackDelayedInternal里面添加的元素,并执行元素里的run函数,整个流程也就跑了一遍。更多Android相关信息见Android 专题页面 http://www.linuxidc.com/topicnews.aspx?tid=11
收藏该网址