ValueAnimation 是如何刷新的

本文详细探讨了ValueAnimation的刷新过程,从ValueAnimator.start()开始,经过AnimationHandler和doAnimationFrame方法,揭示了动画更新和结束的逻辑。接着分析了ViewRootImpl在ValueAnimator使用时如何触发invalidated,以及Choreographer如何通过postCallback和doFrame调度动画帧的刷新,为理解Android动画的内部工作机制提供了深入见解。
摘要由CSDN通过智能技术生成

ValueAnimation 是如何刷新的

背景

之前,技术分享讲过ValueAnimation底层源码。但是,没有提到,Animation的更新。此篇文章,聚焦于ValueAnimation start方法开始,到Choreographer的响应回调。

ValueAnimator部分

ValueAnimator.start()

从思维逻辑上,start方法是动画启动的入口,那绘制应该也从这里开始寻找

	//ValueAnimator
    @Override
    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");
        }
        mReversing = playBackwards;
        mSelfPulse = !mSuppressSelfPulseRequested;
        // Special case: reversing from seek-to-0 should act as if not seeked at all.
        if (playBackwards && mSeekFraction != -1 && mSeekFraction != 0) {
   
            if (mRepeatCount == INFINITE) {
   
                // 计算当前迭代的分数。
                float fraction = (float) (mSeekFraction - Math.floor(mSeekFraction));
                mSeekFraction = 1 - fraction;
            } else {
   
                mSeekFraction = 1 + mRepeatCount - mSeekFraction;
            }
        }
        mStarted = true;
        mPaused = false;
        mRunning = false;
        mAnimationEndRequested = false;
        // 当start()被调用时,重置mLastFrameTime,这样如果动画正在运行,
        // 调用start()将把动画放到已经开始但尚未到达的第一帧阶段。
        mLastFrameTime = -1;
        mFirstFrameTime = -1;
        mStartTime = -1;
        addAnimationCallback(0);

        if (mStartDelay == 0 || mSeekFraction >= 0 || mReversing) {
   
            // 如果没有启动延迟,初始化动画并立即通知启动监听器,
            // 以与前面的行为保持一致。否则,将此延迟到开始延迟后的第一帧。
            startAnimation();
            if (mSeekFraction == -1) {
   
                // 无seek, 0时开始。注意,我们没有使用分数0的原因是,对于持续时间为0的动画,
                // 我们希望与前n的行为保持一致:立即跳到最终值。
                setCurrentPlayTime(0);
            } else {
   
                setCurrentFraction(mSeekFraction);
            }
        }
    }

需求要注意的是,在startAnimation方法中进行数值的初始化,和Linstener的调用。但是不在本篇的范围内,不做分析。其中重点是addAnimationCallback方法。

	//ValueAnimator
	private void addAnimationCallback(long delay) {
   
        if (!mSelfPulse) {
   
            return;
        }
        getAnimationHandler().addAnimationFrameCallback(this, delay);
    }
    
    public AnimationHandler getAnimationHandler() {
   
        return mAnimationHandler != null ? mAnimationHandler : AnimationHandler.getInstance();
    }

AnimationHandler

可以看到,addAnimationCallback方法,最终调用到的是AnimationHandleraddAnimationFrameCallback方法。

	 //AnimationHandler
 	public void addAnimationFrameCallback(final AnimationFrameCallback callback, long delay) {
   
 		//如果之前没有动画要展示,就找provider启动动画循环(假循环)
        if (mAnimationCallbacks.size() == 0) {
   
            getProvider().postFrameCallback(mFrameCallback);
        }
        
        //之前不存在,就往进加
        if (!mAnimationCallbacks.contains(callback)) {
   
            mAnimationCallbacks.add(callback);
        }

        if (delay > 0) {
   
            mDelayedCallbackStartTime.put(callback, (SystemClock.uptimeMillis() + delay));
        }
    }	

注释很清楚,我们应该往getProvider().postFrameCallback里看。

	//AnimationHandler
	 private AnimationFrameCallbackProvider getProvider() {
   
        if (mProvider == null) {
   
            mProvider = new MyFrameCallbackProvider();
        }
        return mProvider;
    }
    
	private class MyFrameCallbackProvider implements AnimationFrameCallbackProvider {
   

        final Choreographer mChoreographer = Choreographer.getInstance();

	  	//就是这里
        @Override
        public void postFrameCallback(Choreographer.FrameCallback callback) {
   
            mChoreographer.postFrameCallback(callback);
        }

        @Override
        public void postCommitCallback(Runnable runnable) {
   
            mChoreographer.postCallback(Choreographer.CALLBACK_COMMIT, runnable, null);
        }

        @Override
        public long getFrameTime() {
   
            return mChoreographer.getFrameTime();
        }

        @Override
        public long getFrameDelay() {
   
            return Choreographer.getFrameDelay();
        }

        @Override
        public void setFrameDelay(long delay) {
   
            Choreographer.setFrameDelay(delay);
        }
    }

我们可以看到,就是往Choreographer里面塞回调。这个Choreographer我们后期会讲到,我们目前只需要知道,当Choreographer收到Vsync后,会依次回调Callback就好了,其中调用onFrame方法。

这里塞的是什么呢?mFrameCallback

	//AnimationHandler
	private final Choreographer.FrameCallback mFrameCallback = new Choreographer.FrameCallback() {
   
        @Override
        public void doFrame(long frameTimeNanos) {
   
            doAnimationFrame(getProvider().getFrameTime());
            if (mAnimationCallbacks.size() > 0) {
   
                getProvider().postFrameCallback(this);
            }
        }
    };

doAnimationFrame

我们看到,会调用,doAnimationFrame

	//AnimationHandler
    private void doAnimationFrame(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值