Android源码 --- 动画分析

动画

本篇记录属性动画执行的原理,本来想通过查看动画相关的源码了解动画执行的原理,没想到后面涉及的东西会越来越多

通过阅读动画相关源码你会了解一下知识:
屏幕刷新原理、Choreographer、VSync,我是看完源码后又看了 胡飞洋 Android屏幕刷新机制—VSync、Choreographer 才大概理解的,还涉及到插值器、估值器。

属性动画

首先ObjectAnimator继承自ValueAnimator,而ValueAnimator也是对动画每个时间点上值处理的关键类。
其大概原理就是 通过ofInt、ofFloat、ofArgb等将属性以及对应的值保存到PropertyValuesHolder中,然后PropertyValuesHolder通过反射将属性值注入到target中,等接收到 VSync 信号,刷新屏幕,就会通过注入的属性值改变 target,形成动画。

从ObjectAnimator的start方法进入会走到ValueAnimator的start方法中

    private void start(boolean playBackwards) {
        if (Looper.myLooper() == null) {
            throw new AndroidRuntimeException("Animators may only be run on Looper threads");
        } else {
            this.mPlayingBackwards = playBackwards;
            this.mCurrentIteration = 0;
            this.mPlayingState = 0;
            this.mStarted = true;
            this.mStartedDelay = false;
            ValueAnimator.AnimationHandler animationHandler = this.getOrCreateAnimationHandler();
            animationHandler.mPendingAnimations.add(this);
            if (this.mStartDelay == 0L) {
                this.setCurrentPlayTime(0L);
                this.mPlayingState = 0;
                this.mRunning = true;
                this.notifyStartListeners();
            }

            animationHandler.start();
        }
    }

从ValueAnimator.AnimationHandler的start方法进入我们即将就会看到Android屏幕刷新的关键类Choreographer

        private void scheduleAnimation() {
            if (!this.mAnimationScheduled) {
                this.mChoreographer.postCallback(1, this, (Object)null);
                this.mAnimationScheduled = true;
            }

        }

这里将ValueAnimator.AnimationHandler作为参数传入,再往下

  private void postCallbackDelayedInternal(int callbackType,
            Object action, Object token, long delayMillis) {
        if (DEBUG_FRAMES) {
            Log.d(TAG, "PostCallback: type=" + callbackType
                    + ", action=" + action + ", token=" + token
                    + ", delayMillis=" + 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);
            }
        }
    }

从scheduleFrameLocked进入DisplayEventReceiver的nativeScheduleVsync方法,注册一个VSync接收垂直同步信号的回调

    private void scheduleFrameLocked(long now) {
        if (!this.mFrameScheduled) {
            this.mFrameScheduled = true;
            if (USE_VSYNC) {
                if (this.isRunningOnLooperThreadLocked()) {
                //如果在当前线程,立即绘制
                    this.scheduleVsyncLocked();
                } else {
                //否则同步到当前线程
                    Message msg = this.mHandler.obtainMessage(1);
                    msg.setAsynchronous(true);
                    this.mHandler.sendMessageAtFrontOfQueue(msg);
                }
            } else {
            //直接绘制
                long nextFrameTime = Math.max(this.mLastFrameTimeNanos / 1000000L + sFrameDelay, now);
                Message msg = this.mHandler.obtainMessage(0);
                msg.setAsynchronous(true);
                this.mHandler.sendMessageAtTime(msg, nextFrameTime);
            }
        }

    }

最后会调用doFrame方法中的doCallbacks,最后获取差值器的值,这个值是0到1间的一个float数,意思是整个动画进程的时间百分比,并通过插值器改变当前帧的值,注入target。

补间动画

补间动画是通过 刷新view,view调用onDraw实现,
Android动画之补间动画TweenAnimation


版权声明:本文为u014720866原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。