1、使用屬性動畫
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "x", 0f, 360f);
animator.setDuration(1000);
animator.start();
以上是使用屬性動畫的簡單例子,從start方法開始執行
2、ObjectAnimator.start
//ObjectAnimator.start
public void start() {
AnimationHandler.getInstance().autoCancelBasedOn(this);
super.start();
}
//ValueAnimator.start
public void start() {
start(false);
}
private void start(boolean playBackwards) {
if (Looper.myLooper() == null) {
throw new AndroidRuntimeException("Animators may only be run on Looper threads");
}
//一大段代碼做狀态設定,省略了
....
addAnimationCallback(0); //見3
if (mStartDelay == 0 || mSeekFraction >= 0 || mReversing) {
startAnimation();
if (mSeekFraction == -1) {
setCurrentPlayTime(0);
} else {
setCurrentFraction(mSeekFraction);
}
}
}
主要是設定下狀态屬性,addAnimationCallback(0)跟蹤進去
3、ValueAnimator.addAnimationCallback
private void addAnimationCallback(long delay) {
if (!mSelfPulse) {
return;
}
//見4、5
getAnimationHandler().addAnimationFrameCallback(this, delay);
//這裡的參數this是AnimationFrameCallback接口的實作,ValueAnimator實作了該接口
}
4、getAnimationHandler
public AnimationHandler getAnimationHandler() {
return AnimationHandler.getInstance();
}
public static AnimationHandler getInstance() {
if (sAnimatorHandler.get() == null) {
sAnimatorHandler.set(new AnimationHandler());
}
return sAnimatorHandler.get();
}
主要是擷取目前線程的AnimationHandler執行個體
5、AnimationHandler.addAnimationFrameCallback
public void addAnimationFrameCallback(final AnimationFrameCallback callback, long delay) {
if (mAnimationCallbacks.size() == 0) {
// 見6
getProvider().postFrameCallback(mFrameCallback);//注意mFrameCallback
}
if (!mAnimationCallbacks.contains(callback)) {
mAnimationCallbacks.add(callback);
}
if (delay > 0) {
mDelayedCallbackStartTime.put(callback, (SystemClock.uptimeMillis() + delay));
}
}
//mFrameCallback的實作
private final Choreographer.FrameCallback mFrameCallback = new Choreographer.FrameCallback() {
@Override
public void doFrame(long frameTimeNanos) {
doAnimationFrame(getProvider().getFrameTime());
if (mAnimationCallbacks.size() > 0) {
getProvider().postFrameCallback(this);
}
}
};
getProvider()方法傳回的MyFrameCallbackProvider執行個體,緊接着調用了postFrameCallback方法,傳入mFrameCallback對象
mFrameCallback實際上在AnimationHandler的一個屬性
6、MyFrameCallbackProvider
private class MyFrameCallbackProvider implements AnimationFrameCallbackProvider {
final Choreographer mChoreographer = Choreographer.getInstance();
@Override
public void postFrameCallback(Choreographer.FrameCallback callback) {
mChoreographer.postFrameCallback(callback);//見7
}
....
}
MyFrameCallbackProvider.postFrameCallback方法實際調了Choreographer.postFrameCallback方法
7、Choreographer.postFrameCallback
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);
}
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);
}
最後到了postCallbackDelayedInternal方法,注意這裡的callbackType是CALLBACK_ANIMATION,callback是上一小節的AnimationHandler的mFrameCallback屬性,delayMillis等于0
8、Choreographer.postCallbackDelayedInternal
private void postCallbackDelayedInternal(int callbackType,
Object action, Object token, long delayMillis) {
synchronized (mLock) {
final long now = SystemClock.uptimeMillis();
final long dueTime = now + delayMillis;
//把mFrameCallback(FrameCallback類型),儲存到數組mCallbackQueues裡面
//下标是callbackType,也就是CALLBACK_ANIMATION,
mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);
//因為delayMillis為0,if成立
if (dueTime <= now) {
scheduleFrameLocked(now);//見9
} else {
//如果不成立,通過handler發送延遲消息,結果也是一樣的
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);
msg.arg1 = callbackType;
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, dueTime);
}
}
}
9、Choreographer.scheduleFrameLocked
//是否使用垂直同步機制,通常為true
private static final boolean USE_VSYNC = SystemProperties.getBoolean(
"debug.choreographer.vsync", true);
private void scheduleFrameLocked(long now) {
if (!mFrameScheduled) {
mFrameScheduled = true;
if (USE_VSYNC) {
// 運作在looper線程
if (isRunningOnLooperThreadLocked()) {
scheduleVsyncLocked();//見10
} else {
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC);
msg.setAsynchronous(true);
mHandler.sendMessageAtFrontOfQueue(msg);
}
} else {
//如果不使用VSYNC垂直同步信号機制,則通過Handler處理,通常不會走到這裡
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);
}
}
}
10、Choreographer.scheduleVsyncLocked
private 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);
}
}
nativeScheduleVsync方法到native層了,當初追蹤到這裡就斷了,後來無意間看到下面的dispatchVsync方法的注釋
Called from native code. 是以猜測native層調了這個方法回到了java層。
11、dispatchVsync
// Called from native code.
@SuppressWarnings("unused")
private void dispatchVsync(long timestampNanos, int builtInDisplayId, int frame) {
onVsync(timestampNanos, builtInDisplayId, frame); //見12
}
接着傳遞到了onVsync方法,FrameDisplayEventReceiver重寫了該方法
12、FrameDisplayEventReceiver.onVsync
public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
...
long now = System.nanoTime();
if (timestampNanos > now) {
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;
Message msg = Message.obtain(mHandler, this); //callback傳了this, 執行下面的run方法
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
}
@Override
public void run() {
mHavePendingVsync = false;
doFrame(mTimestampNanos, mFrame);//見13
}
将vsync事件通過Handler去處理。
13、Choreographer.doFrame
void doFrame(long frameTimeNanos, int frame) {
final long startNanos;
synchronized (mLock) {
if (!mFrameScheduled) {
return; // no work to do
}
long intendedFrameTimeNanos = frameTimeNanos;
startNanos = System.nanoTime();
final long jitterNanos = startNanos - frameTimeNanos;
if (jitterNanos >= mFrameIntervalNanos) {
final long skippedFrames = jitterNanos / mFrameIntervalNanos;
if (skippedFrames >= SKIPPED_FRAME_WARNING_LIMIT) {//SKIPPED_FRAME_WARNING_LIMIT預設30
//注意1 -----------------------------------------------------------
Log.i(TAG, "Skipped " + skippedFrames + " frames! "
+ "The application may be doing too much work on its main thread.");
}
final long lastFrameOffset = jitterNanos % mFrameIntervalNanos;
frameTimeNanos = startNanos - lastFrameOffset;
}
...
}
//以下幾個callback方法做對應事件的處理
//注意2 -----------------------------------------------------------
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);
}
}
注意1:這段日志資訊相信大家都見過,其實就是vsync傳遞過來的時間到目前的時間之間沒處理的幀數是否大于SKIPPED_FRAME_WARNING_LIMIT(預設30);嗯,Choreographer可以做重新整理率的計算
注意2:可以看到回調順序為
- input事件
- 動畫
- view的繪制
14、Choreographer.doCallbacks
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) {
c.run(frameTimeNanos);//見15
}
} finally {
...
}
}
這個方法主要是CallbackRecord.run的執行
15、CallbackRecord.run
public void run(long frameTimeNanos) {
if (token == FRAME_CALLBACK_TOKEN) {
((FrameCallback)action).doFrame(frameTimeNanos);//AnimatorHandler 見16
} else {
((Runnable)action).run();
}
}
action是FrameCallback的執行個體引用,實際上此處就是前文提到的AnimationHandler的mFrameCallback
16、doFrame
public void doFrame(long frameTimeNanos) {
doAnimationFrame(getProvider().getFrameTime());//見17
if (mAnimationCallbacks.size() > 0) {
getProvider().postFrameCallback(this);這裡重複了第5小節的,是以整個動畫架構就構成了一個循環,不斷的去更新
}
}
getProvider().postFrameCallback(this);
這行代碼重複了第5小節的的内容,是以整個動畫架構就構成了一個循環,不斷的去更新。
小結:到這裡可以說已經清楚了整個架構大緻的更新機制了,ObjectAnimator/ValueAnimator通過AnimationHandler間接去調用Choreography,而Choreography封裝了DisplayEventReceiver,DisplayEventReceiver能接收VSYNC垂直同步機制的信号。然後把收到的事件回調給AnimationHandler,而後AnimationHandler在傳遞回去給ObjectAnimator/ValueAnimator。
接着看看AnimationHandler.doAnimationFrame方法是如何把事件傳遞給ValueAnimator的
17、AnimationHandler.doAnimationFrame
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)) {
callback.doAnimationFrame(frameTime);//見18
...
}
}
cleanUpList();
}
主要調了callback.doAnimationFrame(frameTime)方法,callback就是第3小節ValueAnimator.addAnimationCallback方法内部傳遞給AnimationHandler的this對象,是以接下來就是ValueAnimator.doAnimationFrame方法
18、ValueAnimator.doAnimationFrame
public final boolean doAnimationFrame(long frameTime) {
//省略一大段邏輯
...
final long currentTime = Math.max(frameTime, mStartTime);
//animateBasedOnTime傳回值代表動畫是否結束
boolean finished = animateBasedOnTime(currentTime);//見19
//如果結束
if (finished) {
endAnimation();
}
return finished;
}
19、ValueAnimator.animateBasedOnTime
boolean animateBasedOnTime(long currentTime) {
boolean done = false;
if (mRunning) {
final long scaledDuration = getScaledDuration();
//fraction表示單次動畫進度,基于時間,範圍 0~1f
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總的動畫進度,包括重複動畫
mOverallFraction = clampFraction(fraction);
float currentIterationFraction = getCurrentIterationFraction(
mOverallFraction, mReversing);
animateValue(currentIterationFraction);//見20
}
return done;
}
這個方法基于時間做了計算目前動畫進度,然後把進度傳遞給了animateValue方法
20、ValueAnimator.animateValue
@CallSuper
void animateValue(float fraction) {
//mInterpolator是通過setInterpolator方法設定的,預設是AccelerateDecelerateInterpolator
//getInterpolation傳回的fraction是經過TimeInterpolator處理的,getInterpolation方法接收一個基于時間的fraction
fraction = mInterpolator.getInterpolation(fraction);//見22
mCurrentFraction = fraction;
int numValues = mValues.length;
for (int i = 0; i < numValues; ++i) {
mValues[i].calculateValue(fraction);//見23 根據fraction計算動畫真正的值
}
if (mUpdateListeners != null) {
int numListeners = mUpdateListeners.size();
for (int i = 0; i < numListeners; ++i) {
mUpdateListeners.get(i).onAnimationUpdate(this);//回調
}
}
}
把基于時間的fraction通過插值器轉換為基于數值的fraction,然後根據新的fraction通過估值器計算動畫目前真正的數值。
另外可以看到這個方法用了@CallSuper注解,不難猜出子類ObjectAnimator很有可能重寫了該方法。跟進看看
21、ObjectAnimator.animateValue
void animateValue(float fraction) {
final Object target = getTarget();
if (mTarget != null && target == null) {
// We lost the target reference, cancel and clean up. Note: we allow null target if the
/// target has never been set.
cancel();
return;
}
super.animateValue(fraction);
int numValues = mValues.length;
for (int i = 0; i < numValues; ++i) {
mValues[i].setAnimatedValue(target);//這裡應該是通過反射做動畫了
}
}
大膽的猜測mValues[i].setAnimatedValue是通過反射做動畫了,不再跟進了
22、Interpolator.getInterpolation
TimeInterpolator是一個接口,看下最簡單的實作LinearInterpolator
public float getInterpolation(float input) {
return input;
}
果然夠簡單,直接傳回輸入的參數
23、mValues[i].calculateValue(fraction)
mValues是PropertyValuesHolder數組,PropertyValuesHolder.calculateValue最終會走到TypeEvaluator.evaluate方法,看下TypeEvaluator的一個實作IntEvaluator
public class IntEvaluator implements TypeEvaluator<Integer> {
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
int startInt = startValue;
return (int)(startInt + fraction * (endValue - startInt));
}
}
結果就是 開始值+(結束值-開始值)*進度,這裡的fraction就是估值器TimeInterpolator計算的結果