本篇分析与Animator相关的源码
开始
以下为Animator相关类图
Animator是抽象类,ValueAnimator实现了Animator。
通常设置一个ValueAnimator的方法有:
valueAnim = ValueAnimator.ofFloat(0f, 1f);
valueAnim .setDuration(500);
valueAnim .setRepeatMode(ValueAnimator.RESTART);
valueAnim .setRepeatCount(ValueAnimator.INFINITE);
valueAnim .setInterpolator(new LinearInterpolator());
valueAnim .addUpdateListener(animation -> {
float value = (float) animation.getAnimatedValue();
...
});
valueAnim .start();
valueAnim.setStartDelay(500);
下面以几个问题为目标解析ValueAnimator。
一、ValueAnimator如何实现计时?
从start()入手:
...
private void start(boolean playBackwards) { // playBackwards Whether the ValueAnimator
should start playing in reverse.
...
addAnimationCallback(0);// 真正开启计时
...
}
...
@Override
public void start() {
start(false);
}
...
private void addAnimationCallback(long delay) {
if (!mSelfPulse) {
return;
}
// this 即ValueAnimator实现AnimationFrameCallback接口的doAnimationFrame()
getAnimationHandler().addAnimationFrameCallback(this, delay);
}
...
ValueAnimator将计时抛到了AnimatorHandler,ValueAnimator仅接收计时的结果,由doAnimationFrame()接收。
再看AnimationHandler:
...
public void addAnimationFrameCallback(final AnimationFrameCallback callback, long delay) {
if (mAnimationCallbacks.size() == 0) { // 第一次统一使用mFrameCallback接受计时结果
getProvider().postFrameCallback(mFrameCallback);
}
if (!mAnimationCallbacks.contains(callback)) { // mFrameCallback通过mAnimationCallbacks实现监听分发
mAnimationCallbacks.add(callback);
}
if (delay > 0) {
mDelayedCallbackStartTime.put(callback, (SystemClock.uptimeMillis() + delay));
}
}
...
private AnimationFrameCallbackProvider getProvider() {
if (mProvider == null) {
mProvider = new MyFrameCallbackProvider();
}
return mProvider;
}
AnimationHandler又抛到了MyFrameCallbackProvider:
private class MyFrameCallbackProvider implements AnimationFrameCallbackProvider {
final Choreographer mChoreographer = Choreographer.getInstance();
@Override
public void postFrameCallback(Choreographer.FrameCallback callback) {
mChoreographer.postFrameCallback(callback);
}
...
}
接着抛到Choreographer:
...
private final FrameHandler mHandler;
...
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) {
...
synchronized (mLock) {
final long now = SystemClock.uptimeMillis();
final long dueTime = now + delayMillis;
mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);
if (dueTime <= now) { // 此处在MyFrameCallbackProvider没有实现postFrameCallbackDelayed方法,所以不会调用,自定义FrameCallbackProvider可以实现
scheduleFrameLocked(now);
} else {
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);
msg.arg1 = callbackType;
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, dueTime);
}
}
}
...
private final class FrameHandler extends Handler {
public FrameHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_DO_FRAME:
doFrame(System.nanoTime(), 0);
break;
case MSG_DO_SCHEDULE_VSYNC:
doScheduleVsync();
break;
case MSG_DO_SCHEDULE_CALLBACK:
doScheduleCallback(msg.arg1);
break;
}
}
}
Choreographer内部持有FrameHandler,通过Handler的sendMessageAtTime方法实现。到此,计时的位置已经找到了,但是Animator为什么要抛这么多层?抛的好处是什么呢?在此我们需要先了解一些ValueAnimator与AnimatorHandler之间的关系:
这里不贴源码,只阐述:
1)AnimationHandler内部有:
public final static ThreadLocal<AnimationHandler> sAnimatorHandler = new ThreadLocal<>();
确保一个线程下只有一个AnimationHandler。
2)内部Handler一直在计时,不管外部ValueAnimator是否有在运行。当有一个新的Animator开始start时,主动开始一次mHandler.sendMessageAtTime(),所有外部ValueAnimator都能接收到。
3)ValueAnimator的延迟、反转、重复、暂停、唤醒等操作都在其内部内部实现,ValueAnimator与AnimationHandler淡出就是时间片更新监听的关系。
4)我们可以通过ValueAnimator.setFrameDelay(5); // 5ms更新一次时间片,设置的是AnimationHandler -> MyFrameCallbackProvider -> Choreographer 的sFrameDelay字段,会强制对当前线程下所有的ValueAnimator适用。
由上可看出:抛到AnimationHandler是合理的。AnimationHandler再抛到MyFrameCallbackProvider,是桥接模式的使用,方便后续扩展。Choreographer为我们自定义的FrameCallbackProvider提供统一的计时方法,所以MyFrameCallbackProvider将计时再抛到Choreographer。
二、插值器如何实现?
mInterpolator只被ValueAnimator持有:
@Override
public void setInterpolator(TimeInterpolator value) {
if (value != null) {
mInterpolator = value;
} else {
mInterpolator = new LinearInterpolator();
}
}
...
void animateValue(float fraction) {
fraction = mInterpolator.getInterpolation(fraction); // mInterpolator在代码中唯一使用的地方
mCurrentFraction = fraction;
int numValues = mValues.length;
for (int i = 0; i < numValues; ++i) {
mValues[i].calculateValue(fraction);
}
if (mUpdateListeners != null) {
int numListeners = mUpdateListeners.size();
for (int i = 0; i < numListeners; ++i) {
mUpdateListeners.get(i).onAnimationUpdate(this);
}
}
}
mInterpolator仅仅在UpdateListener之前对值进行换算,所以可以理解:传递给animateValue是线性的值,根据不同的插值器进行换算实现结果。
三、ValueAnimator如何实现延迟、反转、重复次数?
入口点:ValueAnimator的doAnimationFrame();
public final boolean doAnimationFrame(long frameTime) { // 返回值其实外部并没有处理
if (mStartTime < 0) {
// mStartDelay为设置(setStartDelay())的延迟时间ms,默认sDurationScale = 1.0f
mStartTime = mReversing ? frameTime : frameTime + (long) (mStartDelay * sDurationScale);
}
// 暂停和唤醒处理
if (mPaused) {
mPauseTime = frameTime;
removeAnimationCallback();
return false;
} else if (mResumed) {
mResumed = false;
if (mPauseTime > 0) {
mStartTime += (frameTime - mPauseTime);
}
}
if (!mRunning) {
if (mStartTime > frameTime && mSeekFraction == -1) { // 不在我们ValueAnimator工作时间内,不处理
return false;
} else { // 从没有运行 -> 运行
mRunning = true;
startAnimation();
}
}
// 以下执行都为运行状态
if (mLastFrameTime < 0) {
if (mSeekFraction >= 0) {
long seekTime = (long) (getScaledDuration() * mSeekFraction);
mStartTime = frameTime - seekTime;
mSeekFraction = -1;
}
mStartTimeCommitted = false;
}
mLastFrameTime = frameTime;
// 比较当前时间片是否在ValueAnimator工作时间内
final long currentTime = Math.max(frameTime, mStartTime);
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;
// 是否开始新的Repeat
final boolean newIteration = (int) fraction > (int) lastFraction;
final boolean lastIterationFinished = (fraction >= mRepeatCount + 1) &&
(mRepeatCount != INFINITE); // mRepeatCount == INFINITE,lastIterationFinished永远为false,再根据newIteration执行下方的①
if (scaledDuration == 0) {// 时间为0时,不考虑其它
done = true;
} else if (newIteration && !lastIterationFinished) {// ① 需要开始新的Repeat
if (mListeners != null) { // 执行Repeat监听
int numListeners = mListeners.size();
for (int i = 0; i < numListeners; ++i) {
mListeners.get(i).onAnimationRepeat(this);
}
}
} else if (lastIterationFinished) {// 不需要开始新的repeat的正常情况
done = true;
}
mOverallFraction = clampFraction(fraction);
float currentIterationFraction = getCurrentIterationFraction(
mOverallFraction, mReversing); // 取值
animateValue(currentIterationFraction);
}
return done;
}
...
private float getCurrentIterationFraction(float fraction, boolean inReverse) {
fraction = clampFraction(fraction);
int iteration = getCurrentIteration(fraction);
float currentFraction = fraction - iteration;
return shouldPlayBackward(iteration, inReverse) ? 1f - currentFraction : currentFraction; // 反转判断
}
看代码中的注释,我们就将以下三个方法都了解完了
valueAnim .setRepeatMode(ValueAnimator.RESTART);
valueAnim .setRepeatCount(ValueAnimator.INFINITE);
valueAnim.setStartDelay(500);
四、再看下ObjectAnimator和TimeAnimator
ObjectAnimator
ObjectAnimator继承于ValueAnimator,先看其构造源码:
...
private <T> ObjectAnimator(T target, Property<T, ?> property) {
setTarget(target);
setProperty(property);
}
...
public static ObjectAnimator ofInt(Object target, String propertyName, int... values) {
ObjectAnimator anim = new ObjectAnimator(target, propertyName);
anim.setIntValues(values);
return anim;
}
...
@Override
public void setTarget(@Nullable Object target) {
final Object oldTarget = getTarget();
if (oldTarget != target) {
if (isStarted()) {
cancel();
}
mTarget = target == null ? null : new WeakReference<Object>(target);
mInitialized = false;
}
}
...
public void setValues(PropertyValuesHolder... values) {
int numValues = values.length;
mValues = values;
mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);
for (int i = 0; i < numValues; ++i) {
PropertyValuesHolder valuesHolder = values[i];
mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder);
}
mInitialized = false;
}
target为ObjectAnimator内部弱引用,mValues是ValueAnimator的成员变量,大部分动画的代码都由ValueAnimator来实现了。
再看ObjectAnimator如何为成员变量进行动态赋值的:
...
public Object getTarget() {
return mTarget == null ? null : mTarget.get();
}
...
@Override
void animateValue(float fraction) {
final Object target = getTarget();
if (mTarget != null && target == null) {
cancel();
return;
}
super.animateValue(fraction);
int numValues = mValues.length;
for (int i = 0; i < numValues; ++i) {
mValues[i].setAnimatedValue(target);
}
}
重载animateValue(),而后对所有的values进行赋值。
TimeAnimator
TimeAnimator.TimeListener:
这个类比较简单,代码很少,主要是对ValueAnimator扩展,实现对动画每一帧的监听。