码迷,mamicode.com
首页 > 其他好文 > 详细

ObjectAnimator.start()工作原理

时间:2016-05-09 00:16:38      阅读:323      评论:0      收藏:0      [点我收藏+]

标签:

分析下面一段代码的逻辑

objectAnimator.start();

他会调用父类的start(),即ValueAnimator,我们分析valueAnimator.start()即可

ValueAnimator:

public void start() {
    start(false);
}
private void start(boolean playBackwards) {

       ...

        AnimationHandler animationHandler = getOrCreateAnimationHandler();
        animationHandler.mPendingAnimations.add(this);

        ...

        animationHandler.start();
    }

ValueAnimator把动画逻辑交给了AnimationHandler。接着看animationHandler.start()

ValueAnimator.AnimationHandler:

public void start() {
            scheduleAnimation();
        }
private void scheduleAnimation() {
            if (!mAnimationScheduled) {
                mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimate, null);
                mAnimationScheduled = true;
            }
        }
mChoreographer是什么?这追溯到AnimationHandler的创建地方。
首先看AnimationHandler创建的机制
ValueAnimator:
private 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:

private AnimationHandler() {
            mChoreographer = Choreographer.getInstance();
        }

接着看Choreographer:

Choreographer:

public static Choreographer getInstance() {
        return sThreadInstance.get();
    }
private static final ThreadLocal<Choreographer> sThreadInstance =
            new ThreadLocal<Choreographer>() {
        @Override
        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:

private Choreographer(Looper looper) {
        mLooper = looper;
        mHandler = new FrameHandler(looper);
        
        ...


    }

Choreographer.FrameHandler:

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是如何使动画跑起来的:

Choreographer:

public 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:

void doScheduleCallback(int callbackType) {
        synchronized (mLock) {
            if (!mFrameScheduled) {
                final long now = SystemClock.uptimeMillis();
                if (mCallbackQueues[callbackType].hasDueCallbacksLocked(now)) {
                    scheduleFrameLocked(now);
                }
            }
        }
    }
private void scheduleFrameLocked(long now) {
        if (!mFrameScheduled) {
            mFrameScheduled = true;
            if (USE_VSYNC) {
                if (DEBUG_FRAMES) {
                    Log.d(TAG, "Scheduling next frame on vsync.");
                }

                // If running on the Looper thread, then schedule the vsync immediately,
                // otherwise post a message to schedule the vsync from the UI thread
                // as soon as possible.
                if (isRunningOnLooperThreadLocked()) {
                    scheduleVsyncLocked();
                } else {
                    Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC);
                    msg.setAsynchronous(true);
                    mHandler.sendMessageAtFrontOfQueue(msg);
                }
            } else {
                final long nextFrameTime = Math.max(
                        mLastFrameTimeNanos / TimeUtils.NANOS_PER_MS + sFrameDelay, now);
                if (DEBUG_FRAMES) {
                    Log.d(TAG, "Scheduling next frame in " + (nextFrameTime - now) + " ms.");
                }
                Message msg = mHandler.obtainMessage(MSG_DO_FRAME);
                msg.setAsynchronous(true);
                mHandler.sendMessageAtTime(msg, nextFrameTime);
            }
        }
    }

USE_VSYNC是垂直同步的意思,使得显卡生成帧的速度和屏幕刷新的速度的保持一致。在此不讨论其细节,假设不开启,因为,如果开启的话,后面的流程最终还是和不开启的流程一样的。

接着看MSG_DO_FRAME分支

Choreographer:

void doFrame(long frameTimeNanos, int frame) {
        ...

        try {
            Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Choreographer#doFrame");

            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 {
            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
        }

        ...
    }
void doCallbacks(int callbackType, long frameTimeNanos) {
        CallbackRecord callbacks;
        synchronized (mLock) {
            // We use "now" to determine when callbacks become due because it‘s possible
            // for earlier processing phases in a frame to post callbacks that should run
            // in a following phase, such as an input event that causes an animation to start.
            final long now = System.nanoTime();
            callbacks = mCallbackQueues[callbackType].extractDueCallbacksLocked(
                    now / TimeUtils.NANOS_PER_MS);
            ...
        }
        try {
            Trace.traceBegin(Trace.TRACE_TAG_VIEW, CALLBACK_TRACE_TITLES[callbackType]);
            for (CallbackRecord c = callbacks; c != null; c = c.next) {
                if (DEBUG_FRAMES) {
                    Log.d(TAG, "RunCallback: type=" + callbackType
                            + ", action=" + c.action + ", token=" + c.token
                            + ", latencyMillis=" + (SystemClock.uptimeMillis() - c.dueTime));
                }
                c.run(frameTimeNanos);
            }
        } finally {
            synchronized (mLock) {
                mCallbacksRunning = false;
                do {
                    final CallbackRecord next = callbacks.next;
                    recycleCallbackLocked(callbacks);
                    callbacks = next;
                } while (callbacks != null);
            }
            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
        }
    }

首先取出CALLBACK_ANIMATION对应的CallbackQueue中的actions列表,然后运行。这样,我们就回到了刚开始使用Choreographer时传入的action。

ValueAnimator.AnimationHandler:

final Runnable mAnimate = new Runnable() {
            @Override
            public void run() {
                mAnimationScheduled = false;
                doAnimationFrame(mChoreographer.getFrameTime());
            }
        };
void doAnimationFrame(long frameTime) {
            mLastFrameTime = frameTime;

            // mPendingAnimations holds any animations that have requested to be started
            // We‘re going to clear mPendingAnimations, but starting animation may
            // cause more to be added to the pending list (for example, if one animation
            // starting triggers another starting). So we loop until mPendingAnimations
            // is empty.
            while (mPendingAnimations.size() > 0) {
                ArrayList<ValueAnimator> pendingCopy =
                        (ArrayList<ValueAnimator>) mPendingAnimations.clone();
                mPendingAnimations.clear();
                int count = pendingCopy.size();
                for (int i = 0; i < count; ++i) {
                    ValueAnimator anim = pendingCopy.get(i);
                    // If the animation has a startDelay, place it on the delayed list
                    if (anim.mStartDelay == 0) {
                        anim.startAnimation(this);
                    } else {
                        mDelayedAnims.add(anim);
                    }
                }
            }

            // Next, process animations currently sitting on the delayed queue, adding
            // them to the active animations if they are ready
            int numDelayedAnims = mDelayedAnims.size();
            for (int i = 0; i < numDelayedAnims; ++i) {
                ValueAnimator anim = mDelayedAnims.get(i);
                if (anim.delayedAnimationFrame(frameTime)) {
                    mReadyAnims.add(anim);
                }
            }
            int numReadyAnims = mReadyAnims.size();
            if (numReadyAnims > 0) {
                for (int i = 0; i < numReadyAnims; ++i) {
                    ValueAnimator anim = mReadyAnims.get(i);
                    anim.startAnimation(this);
                    anim.mRunning = true;
                    mDelayedAnims.remove(anim);
                }
                mReadyAnims.clear();
            }

            // Now process all active animations. The return value from animationFrame()
            // tells the handler whether it should now be ended
            int numAnims = mAnimations.size();
            for (int i = 0; i < numAnims; ++i) {
                mTmpAnimations.add(mAnimations.get(i));
            }
            for (int i = 0; i < numAnims; ++i) {
                ValueAnimator anim = mTmpAnimations.get(i);
                if (mAnimations.contains(anim) && anim.doAnimationFrame(frameTime)) {
                    mEndingAnims.add(anim);
                }
            }
            mTmpAnimations.clear();
            if (mEndingAnims.size() > 0) {
                for (int i = 0; i < mEndingAnims.size(); ++i) {
                    mEndingAnims.get(i).endAnimation(this);
                }
                mEndingAnims.clear();
            }

            ...
            if (!mAnimations.isEmpty() || !mDelayedAnims.isEmpty()) {
                scheduleAnimation();
            }
        }

ValueAnimator:

private void startAnimation(AnimationHandler handler) {
        ...
        initAnimation();
        handler.mAnimations.add(this);
        ...
    }

doAnimationFrame遍历mPendingAnimations,需要执行的ValueAnimator会添加到mAnimations中,遍历mAnimations,然后开始执行真正的动画操作

ValueAnimator:

final 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的核心

  1. 首先根据当前的Interpolator得到对应的fraction。
  2. 然后遍历mValues,执行calculateValue。mValues是一个PropertyValuesHolder集合,PropertyValuesHolder存储着需要动态变化的信息,比如方法名的字符串对象"translationX",这就是我们平时ObjectAnimator.ofFloat提供的方法名啊。执行calculateValue就是利用反射来执行对应的方法(这个细节我还没有仔细看源码),实现真正的动画。
  3. 最后遍历监听器并回调。

动画如何结束呢?我们看回去AnimationHandler的doAnimationFrame方法,里面有这么一段代码:

ValueAnimator.AnimationHandler.doAnimationFrame:

for (int i = 0; i < numAnims; ++i) {
                ValueAnimator anim = mTmpAnimations.get(i);
                if (mAnimations.contains(anim) && anim.doAnimationFrame(frameTime)) {
                    mEndingAnims.add(anim);
                }
            }
            mTmpAnimations.clear();
            if (mEndingAnims.size() > 0) {
                for (int i = 0; i < mEndingAnims.size(); ++i) {
                    mEndingAnims.get(i).endAnimation(this);
                }
                mEndingAnims.clear();
            }

ValueAnimator:

protected void endAnimation(AnimationHandler handler) {
        handler.mAnimations.remove(this);
        handler.mPendingAnimations.remove(this);
        handler.mDelayedAnims.remove(this);
        mPlayingState = STOPPED;
        mPaused = false;
        ...
    }

可见,一个动画如果没有完成就不会添加到mEndingAnims列表,一旦完成了就会加入,并且会被删除掉。自然这个动画就算结束了。

mAnimations只要不为空,那么就会再次调用scheduleAnimation(),如下

ValueAnimator.AnimationHandler.doAnimationFrame:

if (!mAnimations.isEmpty() || !mDelayedAnims.isEmpty()) {
                scheduleAnimation();
            }

总结一下:

  1. ValueAnimator创建时,会获取到本线程的一个AnimationHandler,里面包含一个本线程的Choreographer,Choreographer又包含一个handler(所以要求ValueAnimator创建所在的线程必须是具有looper的)。
  2. ValueAnimator通过AnimationHandler执行动画,AnimationHandler又通过Choreographer中的handler进行不断的回调,ValueAnimator收到回调后利用反射机制执行动画操作。
  3. ObjectAnimator作用的对象如果只能在特定的线程里面操作,ObjectAnimator必须在特定的线程创建,这样才能在特定的线程得到Choreographer中的handler的回调。(比如View只能在主线程操作UI更新)

ObjectAnimator.start()工作原理

标签:

原文地址:http://www.cnblogs.com/linyibiao/p/5472276.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!