先上個(gè)時(shí)序圖章喉,整個(gè)調(diào)用鏈都在圖里了探遵。
源碼
ValueAnimator.java
public void start() {
start(false);
}
private void start(boolean playBackwards) {
//所以在線程中執(zhí)行時(shí)必須得Looper.prepare()
if (Looper.myLooper() == null) {
throw new AndroidRuntimeException("Animators may only be run on Looper threads");
}
...省略
addAnimationCallback(0);
//如果不延遲啟動(dòng)
if (mStartDelay == 0 || mSeekFraction >= 0 || mReversing) {
// If there's no start delay, init the animation and notify start listeners right away
// to be consistent with the previous behavior. Otherwise, postpone this until the first
// frame after the start delay.
//開(kāi)始動(dòng)畫(huà)就乓,回調(diào)動(dòng)畫(huà)開(kāi)始了
startAnimation();
if (mSeekFraction == -1) {
// No seek, start at play time 0. Note that the reason we are not using fraction 0
// is because for animations with 0 duration, we want to be consistent with pre-N
// behavior: skip to the final value immediately.
setCurrentPlayTime(0);
} else {
setCurrentFraction(mSeekFraction);
}
}
}
private void addAnimationCallback(long delay) {
if (!mSelfPulse) {
return;
}
getAnimationHandler().addAnimationFrameCallback(this, delay);
}
public AnimationHandler getAnimationHandler() {
return mAnimationHandler != null ? mAnimationHandler : AnimationHandler.getInstance();
}
初始化動(dòng)畫(huà)拯欧,并將監(jiān)聽(tīng)添加到AnimationHandler
AnimationHandler.java
private final Choreographer.FrameCallback mFrameCallback = new Choreographer.FrameCallback() {
@Override
public void doFrame(long frameTimeNanos) {
doAnimationFrame(getProvider().getFrameTime());
//動(dòng)畫(huà)回調(diào)不為空打颤,繼續(xù)請(qǐng)求信號(hào)量
if (mAnimationCallbacks.size() > 0) {
getProvider().postFrameCallback(this);
}
}
};
public void addAnimationFrameCallback(final AnimationFrameCallback callback, long delay) {
if (mAnimationCallbacks.size() == 0) {
//Frame監(jiān)聽(tīng)
getProvider().postFrameCallback(mFrameCallback);
}
if (!mAnimationCallbacks.contains(callback)) {
//動(dòng)畫(huà)回調(diào)
mAnimationCallbacks.add(callback);
}
if (delay > 0) {
//延遲
mDelayedCallbackStartTime.put(callback, (SystemClock.uptimeMillis() + delay));
}
}
private AnimationFrameCallbackProvider getProvider() {
if (mProvider == null) {
mProvider = new MyFrameCallbackProvider();
}
return mProvider;
}
private class MyFrameCallbackProvider implements AnimationFrameCallbackProvider {
final Choreographer mChoreographer = Choreographer.getInstance();
@Override
public void postFrameCallback(Choreographer.FrameCallback callback) {
//添加Frame監(jiān)聽(tīng)
mChoreographer.postFrameCallback(callback);
}
@Override
public void postCommitCallback(Runnable runnable) {
mChoreographer.postCallback(Choreographer.CALLBACK_COMMIT, runnable, null);
}
@Override
public long getFrameTime() {
return mChoreographer.getFrameTime();
}
@Override
public long getFrameDelay() {
return Choreographer.getFrameDelay();
}
@Override
public void setFrameDelay(long delay) {
Choreographer.setFrameDelay(delay);
}
}
將Frame監(jiān)聽(tīng)添加到Choreographer
Choreographer.java
public void postFrameCallback(FrameCallback callback) {
postFrameCallbackDelayed(callback, 0);
}
public void postFrameCallbackDelayed(FrameCallback callback, long delayMillis) {
if (callback == null) {
throw new IllegalArgumentException("callback must not be null");
}
postCallbackDelayedInternal(CALLBACK_ANIMATION,
callback, FRAME_CALLBACK_TOKEN, delayMillis);
}
private 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) {
...省略
scheduleFrameLocked(now);
}
}
private void scheduleFrameLocked(long now) {
if (!mFrameScheduled) {
mFrameScheduled = true;
if (USE_VSYNC) {
if (DEBUG_FRAMES) {
Log.d(TAG, "Scheduling next frame on vsync.");
}
//是否在主線程籽懦,如果沒(méi)有在主線程則發(fā)送同步消息于个,最終還是會(huì)執(zhí)行scheduleVsyncLocked
if (isRunningOnLooperThreadLocked()) {
scheduleVsyncLocked();
} else {
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);
if (DEBUG_FRAMES) {
Log.d(TAG, "Scheduling next frame in " + (nextFrameTime - now) + " ms.");
}
Message msg = mHandler.obtainMessage(MSG_DO_FRAME);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, nextFrameTime);
}
}
}
private void scheduleVsyncLocked() {
//請(qǐng)求下一個(gè)信號(hào)
mDisplayEventReceiver.scheduleVsync();
}
請(qǐng)求下一個(gè)信號(hào),不明白信號(hào)的可看《Android 底層渲染 - 屏幕刷新機(jī)制源碼分析》
FrameDisplayEventReceiver.java
private final class FrameDisplayEventReceiver extends DisplayEventReceiver
implements Runnable {
private boolean mHavePendingVsync;
private long mTimestampNanos;
private int mFrame;
public FrameDisplayEventReceiver(Looper looper, int vsyncSource) {
super(looper, vsyncSource, CONFIG_CHANGED_EVENT_SUPPRESS);
}
//信號(hào)來(lái)了處理
@Override
public void onVsync(long timestampNanos, long physicalDisplayId, 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.
long now = 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;
}
//handler發(fā)送同步消息暮顺,message的callback就是FrameDisplayEventReceiver
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() {
//handler執(zhí)行
mHavePendingVsync = false;
doFrame(mTimestampNanos, mFrame);
}
}
當(dāng)來(lái)了信號(hào)量后厅篓,執(zhí)行onvsync,發(fā)送Handler同步消息捶码,Message的Callback就是FrameDisplayEventReceiver羽氮,最終通過(guò)Handler執(zhí)行了FrameDisplayEventReceiver.run()方法
DisplayEventReceiver.java
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);
}
}
private static native void nativeScheduleVsync(long receiverPtr);
//分發(fā)信號(hào)量
private void dispatchVsync(long timestampNanos, long physicalDisplayId, int frame) {
onVsync(timestampNanos, physicalDisplayId, frame);
}
請(qǐng)求信號(hào)量,并分發(fā)處理
FrameDisplayEventReceiver.java
void doFrame(long frameTimeNanos, int frame) {
final long startNanos;
synchronized (mLock) {
...省略
try {
...省略
doCallbacks(Choreographer.CALLBACK_ANIMATION, 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.");
}
}
void doCallbacks(int callbackType, long frameTimeNanos) {
CallbackRecord callbacks;
...省略
try {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, CALLBACK_TRACE_TITLES[callbackType]);
for (CallbackRecord c = callbacks; c != null; c = c.next) {
if (DEBUG_FRAMES) {
Log.d(TAG, "RunCallback: type=" + callbackType
+ ", action=" + c.action + ", token=" + c.token
+ ", latencyMillis=" + (SystemClock.uptimeMillis() - c.dueTime));
}
c.run(frameTimeNanos);
}
} finally {
回收CallbackRecord惫恼,和Handler回收Message類(lèi)似
synchronized (mLock) {
mCallbacksRunning = false;
do {
final CallbackRecord next = callbacks.next;
recycleCallbackLocked(callbacks);
callbacks = next;
} while (callbacks != null);
}
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
處理回調(diào)
Choreographer.CallbackRecord.java
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) {
//執(zhí)行Frame回調(diào)
((FrameCallback)action).doFrame(frameTimeNanos);
} else {
((Runnable)action).run();
}
}
}
執(zhí)行Frame回調(diào)
AnimationHandler.java
private final Choreographer.FrameCallback mFrameCallback = new Choreographer.FrameCallback() {
@Override
public void doFrame(long frameTimeNanos) {
doAnimationFrame(getProvider().getFrameTime());
if (mAnimationCallbacks.size() > 0) {
getProvider().postFrameCallback(this);
}
}
};
private void doAnimationFrame(long frameTime) {
long currentTime = SystemClock.uptimeMillis();
final int size = mAnimationCallbacks.size();
for (int i = 0; i < size; i++) {
final AnimationFrameCallback callback = mAnimationCallbacks.get(i);
if (callback == null) {
continue;
}
if (isCallbackDue(callback, currentTime)) {
//動(dòng)畫(huà)回調(diào)
callback.doAnimationFrame(frameTime);
}
}
cleanUpList();
}
幀回調(diào)到動(dòng)畫(huà)回調(diào)
ValueAnimator.java
public final boolean doAnimationFrame(long frameTime) {
...省略
boolean finished = animateBasedOnTime(currentTime);
if (finished) {
endAnimation();
}
return finished;
}
boolean animateBasedOnTime(long currentTime) {
boolean done = false;
if (mRunning) {
final long scaledDuration = getScaledDuration();
final float fraction = scaledDuration > 0 ?
(float)(currentTime - mStartTime) / scaledDuration : 1f;
final float lastFraction = mOverallFraction;
final boolean newIteration = (int) fraction > (int) lastFraction;
final boolean lastIterationFinished = (fraction >= mRepeatCount + 1) &&
(mRepeatCount != INFINITE);
if (scaledDuration == 0) {
// 0 duration animator, ignore the repeat count and skip to the end
done = true;
} else if (newIteration && !lastIterationFinished) {
// Time to repeat
if (mListeners != null) {
int numListeners = mListeners.size();
for (int i = 0; i < numListeners; ++i) {
mListeners.get(i).onAnimationRepeat(this);
}
}
} else if (lastIterationFinished) {
done = true;
}
mOverallFraction = clampFraction(fraction);
float currentIterationFraction = getCurrentIterationFraction(
mOverallFraction, mReversing);
//當(dāng)前進(jìn)度
animateValue(currentIterationFraction);
}
return done;
}
void animateValue(float fraction) {
fraction = mInterpolator.getInterpolation(fraction);
mCurrentFraction = fraction;
int numValues = mValues.length;
for (int i = 0; i < numValues; ++i) {
//計(jì)算值
mValues[i].calculateValue(fraction);
}
if (mUpdateListeners != null) {
int numListeners = mUpdateListeners.size();
for (int i = 0; i < numListeners; ++i) {
//回調(diào)
mUpdateListeners.get(i).onAnimationUpdate(this);
}
}
}
//結(jié)束動(dòng)畫(huà)
private void endAnimation() {
if (mAnimationEndRequested) {
return;
}
//移除動(dòng)畫(huà)監(jiān)聽(tīng)档押,所以再也不會(huì)有幀相關(guān)的計(jì)時(shí)監(jiān)聽(tīng)
removeAnimationCallback();
mAnimationEndRequested = true;
mPaused = false;
boolean notify = (mStarted || mRunning) && mListeners != null;
if (notify && !mRunning) {
// If it's not yet running, then start listeners weren't called. Call them now.
notifyStartListeners();
}
mRunning = false;
mStarted = false;
mStartListenersCalled = false;
mLastFrameTime = -1;
mFirstFrameTime = -1;
mStartTime = -1;
if (notify && mListeners != null) {
ArrayList<AnimatorListener> tmpListeners =
(ArrayList<AnimatorListener>) mListeners.clone();
int numListeners = tmpListeners.size();
for (int i = 0; i < numListeners; ++i) {
tmpListeners.get(i).onAnimationEnd(this, mReversing);
}
}
// mReversing needs to be reset *after* notifying the listeners for the end callbacks.
mReversing = false;
if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
Trace.asyncTraceEnd(Trace.TRACE_TAG_VIEW, getNameForTrace(),
System.identityHashCode(this));
}
}
整個(gè)流程就分析完了。動(dòng)畫(huà)的核心驅(qū)動(dòng)是祈纯,利用屏幕的刷新機(jī)制令宿,請(qǐng)求信號(hào),然后在通過(guò)Handler的同步消息盆繁,執(zhí)行Frame回調(diào)掀淘。Frame回調(diào)中在執(zhí)行動(dòng)畫(huà)回調(diào)。動(dòng)畫(huà)回調(diào)中根據(jù)時(shí)間和動(dòng)畫(huà)插值油昂。計(jì)算出最新的動(dòng)畫(huà)值革娄,回調(diào)給用戶柄驻。ValueAnimation中animateBasedOnTime方法會(huì)返回當(dāng)前動(dòng)畫(huà)是否結(jié)束涡上,如果已經(jīng)結(jié)束就移除動(dòng)畫(huà)回調(diào),如果未結(jié)束FrameCallback的doFrame中處理完這一幀后员寇,會(huì)繼續(xù)請(qǐng)求下一個(gè)信號(hào)量安寺。