天天看點

源碼學習Android屬性動畫流程

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:可以看到回調順序為

  1. input事件
  2. 動畫
  3. 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計算的結果