源码学习Android属性动画流程

本文详细探讨了Android属性动画的工作流程,从ObjectAnimator.start开始,经过ValueAnimator.addAnimationCallback,Choreographer调度,再到AnimationHandler和帧回调,直至最终的插值计算和动画值更新。通过这一系列步骤,揭示了属性动画如何利用VSYNC信号进行帧更新,并通过插值器和估值器实现平滑动画效果。
摘要由CSDN通过智能技术生成
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计算的结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值