本文依据Android 12进行学习研讨,参考《深入了解Android内核源码》思路学习总结,如有了解不对,望各位朋友指正,别的或许留存一些疑问,留后续再探究。输出只是为了分享和提升自己。

动画初始化

依照窗口管理战略类中的界说,动画应该被分为四种类型。

  • TRANSIT_ENTER:窗口进入。
  • TRANSIT_EXIT:窗口移除。
  • TRANSIT_SHOW:窗口可见。
  • TRANSIT_HIDE:窗口隐藏。

TRANSIT_PREVIEW_DONE其实不算是动画,而是一个标志发动窗口完结的标志位。在WMSrelayoutWindow函数,会依据窗口状况判别是否要履行动画。下面代码则是判别动画的起始点。

//仅有在窗口在可见状况下且是一个发动窗口类型或者相关的appToken不隐藏时才会进行从头布局
final boolean shouldRelayout = viewVisibility == View.VISIBLE &&
        (win.mActivityRecord == null || win.mAttrs.type == TYPE_APPLICATION_STARTING
                || win.mActivityRecord.isClientVisible());
//当时不需求从头布局、也已经有Surface,且不是在履行退出动画,则需求考虑是否履行动画
if (!shouldRelayout && winAnimator.hasSurface() && !win.mAnimatingExit) {
    result |= RELAYOUT_RES_SURFACE_CHANGED;
    if (!win.mWillReplaceWindow) {
        ......
        //测验开端或者退出动画    
        focusMayChange = tryStartExitingAnimation(win, winAnimator, focusMayChange);
    }
}

规划之妙,了解Android动画流程

tryStartExitingAnimation调用了WindowStateAnimator类型目标winAnimatorapplyAnimationLocked函数履行动画。

private boolean tryStartExitingAnimation(WindowState win, WindowStateAnimator winAnimator,boolean focusMayChange) {
    int transit = WindowManagerPolicy.TRANSIT_EXIT;
    //特点类型是使用窗口
    if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
      //发动窗口完结
        transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
    }
//窗口处于动画改换
     if (win.inTransition()) {
        focusMayChange = true;
        win.mAnimatingExit = true;
    } else if (win.isWinVisibleLw() && win.mDisplayContent.okToAnimate()) {
        String reason = null;
        //履行动画,假如未履行动画或动画失利,则开释相关资源
        if (winAnimator.applyAnimationLocked(transit, false)) {
            reason = "applyAnimation";
            focusMayChange = true;
            win.mAnimatingExit = true;
        } else if (
                win.isSelfAnimating(0 /* flags */, ANIMATION_TYPE_WINDOW_ANIMATION)
                || win.isAnimating(PARENTS | TRANSITION,ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_RECENTS)|| (win.inTransition()
            reason = "animating";
            win.mAnimatingExit = true;
        } else if (win.mDisplayContent.mWallpaperController.isWallpaperTarget(win)
                && win.mAttrs.type != TYPE_NOTIFICATION_SHADE) {
            reason = "isWallpaperTarget";
            win.mAnimatingExit = true;
        }
    .....
        }
    }
    //资源开释
    if (!win.mAnimatingExit) {
        boolean stopped = win.mActivityRecord == null || win.mActivityRecord.mAppStopped;
        win.mDestroying = true;
        win.destroySurface(false, stopped);
    }
    if (mAccessibilityController.hasCallbacks()) {
        mAccessibilityController.onWindowTransition(win, transit);
    }
    return focusMayChange;
}

applyAnimationLocked函数选择适宜的动画类型,并设置给WindowState,这儿也是 判别是否有设置动画的当地。假如设置了动画,调用WindowStatestartAnimation函数。

boolean applyAnimationLocked(int transit, boolean isEntrance) {
  //防止加载相同动画两次
    if (mWin.isAnimating() && mAnimationIsEntrance == isEntrance) {
        return true;
    }
    if (mWin.mAttrs.type == TYPE_INPUT_METHOD) {
        mWin.getDisplayContent().adjustForImeIfNeeded();
        if (isEntrance) {
            mWin.setDisplayLayoutNeeded();
            mService.mWindowPlacerLocked.requestTraversal();
        }
    }
    if (mWin.mControllableInsetProvider != null) {
        // All our animations should be driven by the insets control target.
        return false;
    }
    // 假如显现处于 frozen状况,则不履行动画
    if (mWin.mToken.okToAnimate()) {
        int anim = mWin.getDisplayContent().getDisplayPolicy().selectAnimation(mWin, transit);
        int attr = -1;
        Animation a = null;
        //anim不等于ANIMATION_STYLEABLE,表明给窗口指定了动画
        if (anim != DisplayPolicy.ANIMATION_STYLEABLE) {//anim不等于0,表明指定了动画
            if (anim != DisplayPolicy.ANIMATION_NONE) {
                //加载动画资源
                a = AnimationUtils.loadAnimation(mContext, anim);
            }
        } else {
          //依据动画类型,选择默认的资源文件
            switch (transit) {
                case WindowManagerPolicy.TRANSIT_ENTER:
                    attr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation;
                    break;
                case WindowManagerPolicy.TRANSIT_EXIT:
                    attr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation;
                    break;
                case WindowManagerPolicy.TRANSIT_SHOW:
                    attr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation;
                    break;
                case WindowManagerPolicy.TRANSIT_HIDE:
                    attr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation;
                    break;
            }
    //加载动画资源
            if (attr >= 0) {
                a = mWin.getDisplayContent().mAppTransition.loadAnimationAttr(
                        mWin.mAttrs, attr, TRANSIT_OLD_NONE);
            }
        }
        if (a != null) {
            mWin.startAnimation(a);//获取到动画资源,开端履行动画Animation目标
            mAnimationIsEntrance = isEntrance;
        }
    } else {
        mWin.cancelAnimation();
    }
    return mWin.isAnimating(0 /* flags */, ANIMATION_TYPE_WINDOW_ANIMATION);
}

WindowState在WMS表明一个窗口目标,startAnimation函数对动画anim进行进行初始化,封装成AnimationAdpater类型的adapter目标,并调用父类WindowContainerstartAnimation函数。WindowContainer界说了窗口和窗口层级之间一些通用接口。WindowContainer用来描绘动画和联络相相关的组件,以及履行动画的。

注意到这儿adpter实践类型是LocalAnimationAdapter,表明该动画不需求持有WindowManager 锁。重点是其构造函数的入参WindowAnimationSpecSurfaceAnimationRunner目标,是后续监听VSYNC进行特点核算的当地。

void startAnimation(Animation anim) {
    if (mControllableInsetProvider != null) {
        return;
    }
    final DisplayInfo displayInfo = getDisplayInfo();
    //初始化宽高
    anim.initialize(mWindowFrames.mFrame.width(), mWindowFrames.mFrame.height(),
            displayInfo.appWidth, displayInfo.appHeight);
    anim.restrictDuration(MAX_ANIMATION_DURATION);
    anim.scaleCurrentDuration(mWmService.getWindowAnimationScaleLocked());
	//SurfaceAnimationRunner类型的 mWmService.mSurfaceAnimationRunner
    final AnimationAdapter adapter = new LocalAnimationAdapter(
            new WindowAnimationSpec(anim, mSurfacePosition, false,
                    0),
            mWmService.mSurfaceAnimationRunner);
    //getPendingTransaction剖析
    startAnimation(getPengetPendingTransaction剖析dingTransaction(), adapter);
    commitPendingTransaction();
}

WindowContainer.startAnimation函数又调用了SurfaceAnimator.startAnimationSurfaceAnimator首要是将一组子Surface经过束缚重置为新的Surface,称为Leach,然后交由AnimationAdapter履行动画。

// mWinAnimator.mLastHidden, ANIMATION_TYPE_WINDOW_ANIMATION
//animationFinishedCallback、animationCancelledCallback、snapshotAnim此刻为null
void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden,
        @AnimationType int type,
        @Nullable OnAnimationFinishedCallback animationFinishedCallback,
        @Nullable Runnable animationCancelledCallback,
        @Nullable AnimationAdapter snapshotAnim) {
    mSurfaceAnimator.startAnimation(t, anim, hidden, type, animationFinishedCallback,
            animationCancelledCallback, snapshotAnim, mSurfaceFreezer);
}

startAnimation建立动画链成功之后,就会调用入参anim履行动画。hidden表明WindowContainer当时持有Surface是否可见。按前面剖析,此刻startAnimation只要前面四个参数有值。三种动画:Surface、adapter、snapshot。

void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden,
        @AnimationType int type,
        @Nullable OnAnimationFinishedCallback animationFinishedCallback,
        @Nullable Runnable animationCancelledCallback,
        @Nullable AnimationAdapter snapshotAnim, @Nullable SurfaceFreezer freezer) {
   //强制撤销与t相同类型的动画,并从头履行
   cancelAnimation(t, true /* restarting */, true /* forwardCancel */);
    mAnimation = anim;
    mAnimationType = type;
    mSurfaceAnimationFinishedCallback = animationFinishedCallback;
    mAnimationCancelledCallback = animationCancelledCallback;
    final SurfaceControl surface = mAnimatable.getSurfaceControl();
    if (surface == null) {
        cancelAnimation();
        return;
    }
    //freezer==null
    mLeash = freezer != null ? freezer.takeLeashForAnimation() : null;
    if (mLeash == null) {
      //创立动画链(SurfaceController),一起也会设置给t
        mLeash = createAnimationLeash(mAnimatable, surface, t, type,
                mAnimatable.getSurfaceWidth(), mAnimatable.getSurfaceHeight(), 0 /* x */,
                0 /* y */, hidden, mService.mTransactionFactory);
        mAnimatable.onAnimationLeashCreated(t, mLeash);
    }
    //开端动画链
    mAnimatable.onLeashAnimationStarting(t, mLeash);
    if (mAnimationStartDelayed) {
        return;
    }
    //此刻履行AnimationAdapter目标mAnimation动画,mInnerAnimationFinishedCallback是WC的监听
    mAnimation.startAnimation(mLeash, t, type, mInnerAnimationFinishedCallback);
   //开端snapshot动画,此刻snapshotAnim==null
   if (snapshotAnim != null) {
        mSnapshot = freezer.takeSnapshotForAnimation();
        if (mSnapshot == null) {
            return;
        }
        mSnapshot.startAnimation(t, snapshotAnim, type);
    }
}

按前面的剖析,这儿mAnimation的实践类型是LocalAnimationAdapter。其startAnimation又调用了SurfaceAnimationRunner目标的startAnimation函数。

先是将动画相关内容封装成RunningAnimation目标,并存放到mPendingAnimations中。

然后向编舞者Choreographer注册了VSYNC监听,这样当信号来暂时,会调用startAnimations函数。

规划之妙,了解Android动画流程

void startAnimation(AnimationSpec a, SurfaceControl animationLeash, Transaction t,
        Runnable finishCallback) {
    synchronized (mLock) {
        final RunningAnimation runningAnim = new RunningAnimation(a, animationLeash,
                finishCallback);
        //这样帧信号来暂时,会履行该Map中所有动画
        mPendingAnimations.put(animationLeash, runningAnim);
        //假如当时动画部推迟履行,则立即向Choreographer注册笔直信号监听
        //这样笔直信号来暂时,履行startAnimations,存在必定推迟
        if (!mAnimationStartDeferred) {
            mChoreographer.postFrameCallback(this::startAnimations);
        }
        //一些动画需求初始并使用一些改换
        applyTransformation(runningAnim, t, 0 /* currentPlayTime */);
    }
}

规划之妙,了解Android动画流程

SurfaceAnimationRunnerstartAnimations函数。

private void startAnimations(long frameTimeNanos) {
    synchronized (mLock) {
        startPendingAnimationsLocked();
    }
    mPowerManagerInternal.setPowerBoost(Boost.INTERACTION, 0);
}

遍历mPendingAnimations中所有等待帧信号降临的RunningAnimation目标,调用startAnimationLocked履行它们。

private void startPendingAnimationsLocked() {
    for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
        startAnimationLocked(mPendingAnimations.valueAt(i));
    }
    mPendingAnimations.clear();
}

SurfaceAnimatorRunner目标,startAnimationLocked首要为每个RunningAnimation动画创立ValueAnimator目标并设置相关参数,并在AnimatorUpdateListener回调中核算动画使用目标的相关特点。

@GuardedBy("mLock")
private void startAnimationLocked(RunningAnimation a) {
    final ValueAnimator anim = mAnimatorFactory.makeAnimator();
    //设置动画相关参数
    anim.overrideDurationScale(1.0f);
    anim.setDuration(a.mAnimSpec.getDuration());
    //更改动画目标相关特点
    anim.addUpdateListener(animation -> {
        synchronized (mCancelLock) {
            if (!a.mCancelled) {
                final long duration = anim.getDuration();
                long currentPlayTime = anim.getCurrentPlayTime();
                if (currentPlayTime > duration) {
                    currentPlayTime = duration;
                }
                //每次更改相关动画特点
                applyTransformation(a, mFrameTransaction, currentPlayTime);
            }
        }
        scheduleApplyTransaction();
    });
	//anim开端后,会回调此处。
    anim.addListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationStart(Animator animation) {
            synchronized (mCancelLock) {
                if (!a.mCancelled) {
                    mFrameTransaction.setAlpha(a.mLeash, 1);
                }
            }
        }
        @Override
        public void onAnimationEnd(Animator animation) {
            synchronized (mLock) {
                mRunningAnimations.remove(a.mLeash);
                synchronized (mCancelLock) {
                    if (!a.mCancelled) {
                        mAnimationThreadHandler.post(a.mFinishCallback);
                    }
                }
            }
        }
    });
    a.mAnim = anim;
    mRunningAnimations.put(a.mLeash, a);
	//调用ValueAnimator的start函数。
    anim.start();
    if (a.mAnimSpec.canSkipFirstFrame()) {
        anim.setCurrentPlayTime(mChoreographer.getFrameIntervalNanos() / NANOS_PER_MS);
    }
	//手动触发一帧动画特点
    anim.doAnimationFrame(mChoreographer.getFrameTime());
}

ValueAnimator.start=>start(false),该函数首要ValueAnimator目标对一些变量进行初始化。其间调用了addAnimationCallback(0)AnimationHandler注册帧信号的监听。

private void start(boolean playBackwards) {
    if (Looper.myLooper() == null) {
        throw new AndroidRuntimeException("Animators may only be run on Looper threads");
    }
    mReversing = playBackwards;//此刻false,表明为正向动画
    mSelfPulse = !mSuppressSelfPulseRequested;
    //判别是否快进到某个时刻点
    if (playBackwards && mSeekFraction != -1 && mSeekFraction != 0) {
        if (mRepeatCount == INFINITE) {
            // Calculate the fraction of the current iteration.
            float fraction = (float) (mSeekFraction - Math.floor(mSeekFraction));
            mSeekFraction = 1 - fraction;
        } else {
            mSeekFraction = 1 + mRepeatCount - mSeekFraction;
        }
    }
    mStarted = true;
    mPaused = false;
    mRunning = false;
    mAnimationEndRequested = false;
    mLastFrameTime = -1;
    mFirstFrameTime = -1;
    mStartTime = -1;
    addAnimationCallback(0);
    if (mStartDelay == 0 || mSeekFraction >= 0 || mReversing) {
        //内部初始化动画目标所使用的特点,和回调开端监听
        startAnimation();
        //初始化mStartTime
        if (mSeekFraction == -1) {
            setCurrentPlayTime(0);
        } else {
            setCurrentFraction(mSeekFraction);
        }
    }
}

AnimationHandler在线程中静态单例的,在默认状况下,向编舞者Choreographer注册并接纳其帧信号(笔直信号)回调, 向所有的动画ValueAnimator目标发送刷新帧的时刻,这样它们在同一个线程以相同的时刻履行各自窗口特点值的核算,抵达视觉动画作用。AnimationHandler也为咱们供给 设置类似编舞者供给周期信号的 接口,方便测验和特定功能开发。

private void addAnimationCallback(long delay) {
    if (!mSelfPulse) {
        return;
    }
    getAnimationHandler().addAnimationFrameCallback(this, delay);
}
public 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));
    }
}
//这样笔直信号降临,会调用doFrame函数
private final Choreographer.FrameCallback mFrameCallback = new Choreographer.FrameCallback() {
    @Override
    public void doFrame(long frameTimeNanos) {
        doAnimationFrame(getProvider().getFrameTime());
        if (mAnimationCallbacks.size() > 0) {
            getProvider().postFrameCallback(this);
        }
    }
};

动画触发

规划之妙,了解Android动画流程

AnimationHandler默认状况会向编舞者Choreographer注册笔直信号(VSYNC)监听,这样当笔直信号来暂时,就回调mFrameCallback目标doFrame函数。

doFrame函数获取当时帧时刻并传递给doAnimationFrame函数,假如履行完之后,还有动画没有履行完结则再次监听VSYNC。所以在doAnimationFrame函数中履行动画完毕后肯定将AnimationFrameCallback目标从mAnimationCallbacks移除。

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函数遍历mAnimationCallbacks中所有AnimationFrameCallback目标,判别其是否抵达开端履行动画(部分动画或许设置延时履行),抵达开端时刻,则调用它们的doAnimationFrame函数。

private void doAnimationFrame(long frameTime) {
    long currentTime = SystemClock.uptimeMillis();
    final int size = mAnimationCallbacks.size();
    for (int i = 0; i < size; i++) {
        final AnimationFrameCallback callback = mAnimationCallbacks.get(i);
        if (callback == null) {
            continue;
        }
        //判别动画是否抵达开端履行时刻
        if (isCallbackDue(callback, currentTime)) {
            callback.doAnimationFrame(frameTime);//回调AnimationFrameCallback,进行逻辑处理
            if (mCommitCallbacks.contains(callback)) {//检查在哪里注册到该map,推迟大的时分
                getProvider().postCommitCallback(new Runnable() {
                    @Override
                    public void run() {
                        //延时问题
                        commitAnimationFrame(callback, getProvider().getFrameTime());
                    }
                });
            }
        }
    }
    cleanUpList();
}

ValueAnimator目标doAnimationFrame函数。在VSYNC来暂时,需求依据一些状况调整动画的开端时刻mStartTime。动画未开端、康复动画、暂停动画、动画快进、动画推迟履行都会调整动画的开端时刻。假如此刻动画未开端,此帧时刻则是开端时刻,或者开端倒计时的时刻(动画设置延时履行)。假如当时是康复动画,开端时刻则更改为当时时刻节点+已暂停时刻(mStartTime+elapseTime),而不是停留在前次动画的帧时刻。这儿或许会了解为从继续前次暂停的动画作用,然后继续履行后续动画。假如此刻仍是榜首帧时刻,还需求判别是否存在动画快进的状况。

终究调用animateBasedOnTime函数核算此刻此刻动画的相关特点值。参数为帧时刻(开端之后)或者开端时刻(刚开端)。

public final boolean doAnimationFrame(long frameTime) {
  //动画刚初始化,mStartTime=-1,未开端
    if (mStartTime < 0) {
        // 榜首帧动画时刻,假如有推迟开端动画,此刻开端倒计时
        mStartTime = mReversing
                ? frameTime
                : frameTime + (long) (mStartDelay * resolveDurationScale());
    }
    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) {
            return false;
        } else {
            mRunning = true;
    //初始化ValueAnimator中各个特点值
            startAnimation();
        }
    }
    if (mLastFrameTime < 0) {//此次榜首帧时刻
        if (mSeekFraction >= 0) {
            long seekTime = (long) (getScaledDuration() * mSeekFraction);
            mStartTime = frameTime - seekTime;
            mSeekFraction = -1;
        }
        mStartTimeCommitted = false; // allow start time to be compensated for jank
    }
    mLastFrameTime = frameTime;
    //防止当时帧时刻比开端时刻早的问题
    final long currentTime = Math.max(frameTime, mStartTime);
//核算特点值
    boolean finished = animateBasedOnTime(currentTime);
    if (finished) {
        endAnimation();//移除FrameCallback监听,通知已注册监听
    }
    return finished;
}

咱们知道动画是可以指定重复次数或无限循环的。所以animateBasedOnTime函数核算出本次帧时刻来暂时,本次动画进展在整体进展状况fraction。0表明刚开端履行动画;0-1表明榜首次动画某个时刻点;等于1表明刚好履行完榜首次动画;大于1则表明开端循环动画。当大于1时,正数部分表明第几次重复动画,而小数部分表明本次动画的时刻节点;正数部分假如大于前次fraction,则表明是新的循环。

这个函数有许多规划妙处。

boolean animateBasedOnTime(long currentTime) {
    boolean done = false;
    if (mRunning) {
        //获取持续时刻
        final long scaledDuration = getScaledDuration();
        //currentTime - mStartTime表明动画已履行完的时刻长度,等于0表明刚开端,大于0,说明要越过这部分时刻。
        //(float)(currentTime - mStartTime) / scaledDuration大于1表明已经开端重复履行动画了,0-1则是榜首次。1刚好榜首次动画完毕
        final float fraction = scaledDuration > 0 ?
                (float)(currentTime - mStartTime) / scaledDuration : 1f;
        final float lastFraction = mOverallFraction;
        //fraction在整型比上一次大,则判别为新一次循环,持平判别为同一次动画内的不同阶段
        final boolean newIteration = (int) fraction > (int) lastFraction;
        //判别是否终究一次动画循环:在有限循环次数内,本次动画等于或超出设置的总重复次数
        final boolean lastIterationFinished = (fraction >= mRepeatCount + 1) &&
                (mRepeatCount != INFINITE);
        if (scaledDuration == 0) {
            //持续时刻为0的,直接完毕
            done = true;
        } else if (newIteration && !lastIterationFinished) {
            // 当时属于新的迭代次数,且还没有完毕动画
            if (mListeners != null) {
                int numListeners = mListeners.size();
                for (int i = 0; i < numListeners; ++i) {
                    mListeners.get(i).onAnimationRepeat(this);
                }
            }
        } else if (lastIterationFinished) {
            done = true;//当时属于终究一次迭代
        }
        mOverallFraction = clampFraction(fraction);//缓存本次进展节点
        //先核算本次动画是第几次iteration
        //再取小数部分curFraction=fraction-iteration,依据是否反向动画,确定终究的进展curFraction or 1-curFraction
        float currentIterationFraction = getCurrentIterationFraction(
                mOverallFraction, mReversing);
        animateValue(currentIterationFraction);//经过插值器核算动画特点值
    }
    return done;
}

animateValue函数以本次动画时刻进展节点,经过时刻插值器改换进展节点,然后通知特点数组mValues中的目标,让它们依据改换后fraction,转化具体的特点值。然后回调UpdateListener目标的onAnimationUpdate函数。

void animateValue(float fraction) {
	//插值器改换fraction
    fraction = mInterpolator.getInterpolation(fraction);
    mCurrentFraction = fraction;
    int numValues = mValues.length;
    for (int i = 0; i < numValues; ++i) {
    	//各个特点依据fraction转化自己的值
        mValues[i].calculateValue(fraction);
    }
    if (mUpdateListeners != null) {
        int numListeners = mUpdateListeners.size();
        for (int i = 0; i < numListeners; ++i) {
        	//回调通知
            mUpdateListeners.get(i).onAnimationUpdate(this);
        }
    }
}

这就回到了SurfaceAnimatorRunner对像startAnimationLocked函数给ValueAnimator设置监听的当地。

private void startAnimationLocked(RunningAnimation a) {
    ......
    //帧动画经过valueAnimator核算发生后回调此处
    anim.addUpdateListener(animation -> {
        synchronized (mCancelLock) {
            if (!a.mCancelled) {
                final long duration = anim.getDuration();
                long currentPlayTime = anim.getCurrentPlayTime();
                if (currentPlayTime > duration) {//履行完毕
                    currentPlayTime = duration;
                }
                //动画特点核算
                applyTransformation(a, mFrameTransaction, currentPlayTime);
            }
        }
        // Transaction will be applied in the commit phase.
        scheduleApplyTransaction();
    });
    ......
}

applyTransformation函数内部有调用了WindowAnimationSpec目标的apply函数。

private void applyTransformation(RunningAnimation a, Transaction t, long currentPlayTime) {
    a.mAnimSpec.apply(t, a.mLeash, currentPlayTime);
}

apply函数获取线程本地TmpValues目标,将相关特点核算结果写到其Transformation类型的transformation成员变量。Transformation类封装Matrix、裁剪、透明度、动画类型。而Matrix可以对目标进行缩放、平移、和旋转。也就是说,Transformation类型囊括了四个动画类型缩放、平移、旋转、透明度,代表了动画某刻要使用的改换。

public void apply(Transaction t, SurfaceControl leash, long currentPlayTime) {
    final TmpValues tmp = mThreadLocalTmps.get();
    //重置transformation
    tmp.transformation.clear();
    //核算某个时刻的动画特点,并将结果写会tmp.transformation
    mAnimation.getTransformation(currentPlayTime, tmp.transformation);
    //位移
    tmp.transformation.getMatrix().postTranslate(mPosition.x, mPosition.y);
    //旋转、缩放
    t.setMatrix(leash, tmp.transformation.getMatrix(), tmp.floats);
    //透明度
    t.setAlpha(leash, tmp.transformation.getAlpha());
    boolean cropSet = false;
    if (mRootTaskClipMode == ROOT_TASK_CLIP_NONE) {
        if (tmp.transformation.hasClipRect()) {
            t.setWindowCrop(leash, tmp.transformation.getClipRect());
            cropSet = true;
        }
    } else {
        mTmpRect.set(mRootTaskBounds);
        if (tmp.transformation.hasClipRect()) {
            mTmpRect.intersect(tmp.transformation.getClipRect());
        }
        t.setWindowCrop(leash, mTmpRect);
        cropSet = true;
    }
    //设置圆角
    if (cropSet && mAnimation.hasRoundedCorners() && mWindowCornerRadius > 0) {
        t.setCornerRadius(leash, mWindowCornerRadius);
    }
}

代码中调用了AnimationgetTransformation函数,首要是核算动画的状况,是否开端、运转、完毕。假如动画仍是处于运转状况,则调用getTransformationAt函数。

public boolean getTransformation(long currentTime, Transformation outTransformation) {
    if (mStartTime == -1) {
        mStartTime = currentTime;
    }
    final long startOffset = getStartOffset();
    final long duration = mDuration;
    float normalizedTime;
	//核算此刻在本次动画的时刻节点
    if (duration != 0) {
		//核算当时所处的方位0
        normalizedTime = ((float) (currentTime - (mStartTime + startOffset))) /
                (float) duration;
    } else {
        //未开端或者完毕了
        normalizedTime = currentTime < mStartTime ? 0.0f : 1.0f;
    }
	//动画完毕了,或者被撤销。
    final boolean expired = normalizedTime >= 1.0f || isCanceled();
    mMore = !expired;
    if (!mFillEnabled) normalizedTime = Math.max(Math.min(normalizedTime, 1.0f), 0.0f);
    if ((normalizedTime >= 0.0f || mFillBefore) && (normalizedTime <= 1.0f || mFillAfter)) {
        if (!mStarted) {
            fireAnimationStart();//回调监听
            mStarted = true;
            if (NoImagePreloadHolder.USE_CLOSEGUARD) {
                guard.open("cancel or detach or getTransformation");
            }
        }
		//normalized在0f~1f之间
        if (mFillEnabled) normalizedTime = Math.max(Math.min(normalizedTime, 1.0f), 0.0f);
		//此刻是否反向动画
        if (mCycleFlip) {
            normalizedTime = 1.0f - normalizedTime;
        }
		//将动画特点缓冲到outTransformation
        getTransformationAt(normalizedTime, outTransformation);
    }
	//完毕了,但是或许循环动画
    if (expired) {
        if (mRepeatCount == mRepeated || isCanceled()) {//动画完毕
            if (!mEnded) {
                mEnded = true;
                guard.close();
                fireAnimationEnd();
            }
        } else {//动画循环
            if (mRepeatCount > 0) {
                mRepeated++;
            }
            if (mRepeatMode == REVERSE) {
                mCycleFlip = !mCycleFlip;
            }
            mStartTime = -1;
            mMore = true;
            fireAnimationRepeat();
        }
    }
    if (!mMore && mOneMoreTime) {
        mOneMoreTime = false;
        return true;
    }
    return mMore;
}

getTransformationAt函数内部又调用AnimationapplyTransformation函数。这儿的Animation子类会重写该函数,完成自己的特定特点核算。Animation子类可所以在主题或者指定的Animation为准,如前面由系统默认指定的动画。

public void getTransformationAt(float normalizedTime, Transformation outTransformation) {
    final float interpolatedTime = mInterpolator.getInterpolation(normalizedTime);
    applyTransformation(interpolatedTime, outTransformation);
}

动画的展示

回到了SurfaceAnimatorRunner对像startAnimationLocked函数给ValueAnimator设置监听的当地。在上面履行了applyTransformation函数之后,调用了applyTransformation。

private final Runnable mApplyTransactionRunnable = this::applyTransaction;
private void scheduleApplyTransaction() {
    if (!mApplyScheduled) {
        mChoreographer.postCallback(CALLBACK_TRAVERSAL, mApplyTransactionRunnable,
                null /* token */);
        mApplyScheduled = true;
    }
}
private void applyTransaction() {
    mFrameTransaction.setAnimationTransaction();
    mFrameTransaction.setFrameTimelineVsync(mChoreographer.getVsyncId());
    mFrameTransaction.apply();
    mApplyScheduled = false;
}

依据前面mSurfaceAnimationRunner目标来自WMS的成员变量,其在WMS创立的时分被创立,Transaction类型的mFrameTransaction目标以同步方式设置SurfaceController。applyTransaction函数调用mFrameTransaction目标的几个方法,内部都调用底层代码去设置Surface。这儿不再进一步跟进。

总结

经过本文对动画源码的学习,了解在动画上面临Float浮点数奇妙运用,用来合理操控动画的重复行为和单次进展。

一起也了解到动画在底层也是经过ValueAnimator来核算动画的各个特点 ,因而进一步确定原理,动画就是在指定的时刻内播放一帧帧图像,依据人眼对图像的感知特色,然后构成动效

别的,动画会以笔直信号来初始化动画和触发动画的开端。