分析下面一段代码的逻辑
1 | objectAnimator.start(); |
他会调用父类的start(),即ValueAnimator,我们分析valueAnimator.start()即可
ValueAnimator:1
2
3
4
5
6
7
8
9
10
11
12
13
14public void start() {
start(false);
}
private void start(boolean playBackwards) {
...
AnimationHandler animationHandler = getOrCreateAnimationHandler();
animationHandler.mPendingAnimations.add(this);
...
animationHandler.start();
}
ValueAnimator把动画逻辑交给了AnimationHandler。接着看animationHandler.start()
ValueAnimator.AnimationHandler:1
2
3
4
5
6
7
8
9public void start() {
scheduleAnimation();
}
private void scheduleAnimation() {
if (!mAnimationScheduled) {
mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimate, null);
mAnimationScheduled = true;
}
}
mChoreographer是什么?这追溯到AnimationHandler的创建地方。
首先看AnimationHandler创建的机制
ValueAnimator:1
2
3
4
5
6
7
8
9
10
11private static AnimationHandler getOrCreateAnimationHandler() {
AnimationHandler handler = sAnimationHandler.get();
if (handler == null) {
handler = new AnimationHandler();
sAnimationHandler.set(handler);
}
return handler;
}
protected static ThreadLocal<AnimationHandler> sAnimationHandler =
new ThreadLocal<AnimationHandler>();
所以一个线程中只有一个AnimationHandler。
接着看AnimationHandler创建细节
ValueAnimator.AnimationHandler:1
2
3private AnimationHandler() {
mChoreographer = Choreographer.getInstance();
}
接着看Choreographer:
Choreographer:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public static Choreographer getInstance() {
return sThreadInstance.get();
}
private static final ThreadLocal<Choreographer> sThreadInstance =
new ThreadLocal<Choreographer>() {
protected Choreographer initialValue() {
Looper looper = Looper.myLooper();
if (looper == null) {
throw new IllegalStateException("The current thread must have a looper!");
}
return new Choreographer(looper);
}
};
可见Choreographer也是每个线程只有一个,而且他指明了只有在具有looper的线程下才能创建成功,这是因为他会创建一个handler
Choreographer:1
2
3
4
5
6
7
8private Choreographer(Looper looper) {
mLooper = looper;
mHandler = new FrameHandler(looper);
...
}
Choreographer.FrameHandler:
1 | private final class FrameHandler extends Handler { |
我们再回头看看Choreographer是如何使动画跑起来的:
Choreographer:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29public void postCallback(int callbackType, Runnable action, Object token) {
postCallbackDelayed(callbackType, action, token, 0);
}
public void postCallbackDelayed(int callbackType,
Runnable action, Object token, long delayMillis) {
...
postCallbackDelayedInternal(callbackType, action, 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) {
scheduleFrameLocked(now);
} else {
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);
msg.arg1 = callbackType;
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, dueTime);
}
}
}
可以知道他把action存储到了mCallbackQueues数组中的下标为CALLBACK_ANIMATION(1)的CallbackQueue中。
因为delayMillis为0,所以他会发送一个what为MSG_DO_SCHEDULE_CALLBACK的Message到mHandler去处理。
根据上面的what分支看下去
Choreographer:
1 | void doScheduleCallback(int callbackType) { |
USE_VSYNC是垂直同步的意思,使得显卡生成帧的速度和屏幕刷新的速度的保持一致。在此不讨论其细节,假设不开启,因为,如果开启的话,后面的流程最终还是和不开启的流程一样的。
接着看MSG_DO_FRAME分支
Choreographer:
1 | void doFrame(long frameTimeNanos, int frame) { |
首先取出CALLBACK_ANIMATION对应的CallbackQueue中的actions列表,然后运行。这样,我们就回到了刚开始使用Choreographer时传入的action。
ValueAnimator.AnimationHandler:
1 | final Runnable mAnimate = new Runnable() { |
ValueAnimator:1
2
3
4
5
6private void startAnimation(AnimationHandler handler) {
...
initAnimation();
handler.mAnimations.add(this);
...
}
doAnimationFrame遍历mPendingAnimations,需要执行的ValueAnimator会添加到mAnimations中,遍历mAnimations,然后开始执行真正的动画操作
ValueAnimator:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31final boolean doAnimationFrame(long frameTime) {
...
return animationFrame(currentTime);
}
boolean animationFrame(long currentTime) {
boolean done = false;
switch (mPlayingState) {
case RUNNING:
case SEEKED:
float fraction = mDuration > 0 ? (float)(currentTime - mStartTime) / mDuration : 1f;
...
animateValue(fraction);
break;
}
return done;
}
void animateValue(float fraction) {
fraction = mInterpolator.getInterpolation(fraction);
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);
}
}
}
animateValue方法就是ValueAnimator的核心
首先根据当前的Interpolator得到对应的fraction。
然后遍历mValues,执行calculateValue。mValues是一个PropertyValuesHolder集合,PropertyValuesHolder存储着需要动态变化的信息,比如方法名的字符串对象”translationX”,这就是我们平时ObjectAnimator.ofFloat提供的方法名啊。执行calculateValue就是利用反射来执行对应的方法(这个细节我还没有仔细看源码),实现真正的动画。
最后遍历监听器并回调。
动画如何结束呢?我们看回去AnimationHandler的doAnimationFrame方法,里面有这么一段代码:
ValueAnimator.AnimationHandler.doAnimationFrame:
1 | for (int i = 0; i < numAnims; ++i) { |
ValueAnimator:
1 | protected void endAnimation(AnimationHandler handler) { |
可见,一个动画如果没有完成就不会添加到mEndingAnims列表,一旦完成了就会加入,并且会被删除掉。自然这个动画就算结束了。
mAnimations只要不为空,那么就会再次调用scheduleAnimation(),如下
ValueAnimator.AnimationHandler.doAnimationFrame:1
2
3if (!mAnimations.isEmpty() || !mDelayedAnims.isEmpty()) {
scheduleAnimation();
}
总结一下:
ValueAnimator创建时,会获取到本线程的一个AnimationHandler,里面包含一个本线程的Choreographer,Choreographer又包含一个handler(所以要求ValueAnimator创建所在的线程必须是具有looper的)。
ValueAnimator通过AnimationHandler执行动画,AnimationHandler又通过Choreographer中的handler进行不断的回调,ValueAnimator收到回调后利用反射机制执行动画操作。
ObjectAnimator作用的对象如果只能在特定的线程里面操作,ObjectAnimator必须在特定的线程创建,这样才能在特定的线程得到Choreographer中的handler的回调。(比如View只能在主线程操作UI更新)
android26的更改
ValueAnimator1
2
3
4
5
6
7
8
9
10
11private void start(boolean playBackwards) {
...
addAnimationCallback(0);
...
}
private void addAnimationCallback(long delay) {
if (!mSelfPulse) {
return;
}
getAnimationHandler().addAnimationFrameCallback(this, delay);
}
ValueAnimator.AnimationHandler:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47public void addAnimationFrameCallback(final AnimationFrameCallback callback, long delay) {
if (mAnimationCallbacks.size() == 0) {
getProvider().postFrameCallback(mFrameCallback);
}
if (!mAnimationCallbacks.contains(callback)) {
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();
public void postFrameCallback(Choreographer.FrameCallback callback) {
mChoreographer.postFrameCallback(callback);
}
public void postCommitCallback(Runnable runnable) {
mChoreographer.postCallback(Choreographer.CALLBACK_COMMIT, runnable, null);
}
public long getFrameTime() {
return mChoreographer.getFrameTime();
}
public long getFrameDelay() {
return Choreographer.getFrameDelay();
}
public void setFrameDelay(long delay) {
Choreographer.setFrameDelay(delay);
}
}