广告
返回顶部
首页 > 资讯 > 移动开发 >Android动画(四)动画框架源码分析
  • 233
分享到

Android动画(四)动画框架源码分析

源码框架Android 2022-06-06 13:06:57 233人浏览 泡泡鱼
摘要

本篇难度较大,慎入 也许可以先去看总结在来一起分析 从我们写的开始进入: fun click(view: View) { va

本篇难度较大,慎入

也许可以先去看总结在来一起分析
从我们写的开始进入:

 fun click(view: View) {
        val textView = findViewById(R.id.tv)
        val animator = ObjectAnimator.ofFloat(textView,"scale", 0f, 1f)
        animator.duration = 3000
        animator.interpolator = LinearInterpolator()
        animator.start()
    }

首先第三行:

val animator = ObjectAnimator.ofFloat()

调用ofFloat()静态方法初始化一个ObjectAnimator对象,进去:

public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) {
        ObjectAnimator anim = new ObjectAnimator(target, propertyName);
        anim.setFloatValues(values);
        return anim;
    }

第二行创建对象,没多大讲法
第三行,设值,点进去看

@Override
    public void setFloatValues(float... values) {
        if (mValues == null || mValues.length == 0) {//values没有设置
            // No values yet - this animator is being constructed piecemeal. Init the values with
            // whatever the current propertyName is
            if (mProperty != null) {//判断我们传入的属性名是否为空
                setValues(PropertyValuesHolder.ofFloat(mProperty, values));
            } else {
                setValues(PropertyValuesHolder.ofFloat(mPropertyName, values));
            }
        } else {
            super.setFloatValues(values);
        }
    }

发现做了一些判断,按上面我们自己写的方法,就会调用

setValues(PropertyValuesHolder.ofFloat(mProperty, values))

首先方法里边实例化PropertyValuesHolder
PropertyValuesHolder.ofFloat(mProperty, values)

所以点进去看来到PropertyValuesHolder这个类下:

public static PropertyValuesHolder ofFloat(Property property, float... values) {
        return new FloatPropertyValuesHolder(property, values);
    }

调用了内部静态类FloatPropertyValuesHolder的构造方法:(FloatPropertyValuesHolder不仅是PropertyValuesHolder的静态内部类,它还继承了PropertyValuesHolder)

public FloatPropertyValuesHolder(Property property, float... values) {
            super(property);
            setFloatValues(values);
            if (property instanceof  FloatProperty) {
                mFloatProperty = (FloatProperty) mProperty;
            }
        }

第三行调用

setFloatValues(values)

@Override
        public void setFloatValues(float... values) {
            super.setFloatValues(values);
            mFloaTKEyframes = (Keyframes.FloatKeyframes) mKeyframes;
        }

第二行,调用父类也就是PropertyValuesHolder的

setFloatValues()
方法:

PropertyValuesHolder类下的:
public void setFloatValues(float... values) {
        mValueType = float.class;
        mKeyframes = KeyframeSet.ofFloat(values);
    }

在第二行做了一个很关键的事情

mKeyframes = KeyframeSet.ofFloat(values);

点进去来到keyFrameSet的:

public static KeyframeSet ofFloat(float... values) {
        boolean badValue = false;
        int numKeyframes = values.length;
        FloatKeyframe keyframes[] = new FloatKeyframe[Math.max(numKeyframes,2)];
        if (numKeyframes == 1) {
            keyframes[0] = (FloatKeyframe) Keyframe.ofFloat(0f);
            keyframes[1] = (FloatKeyframe) Keyframe.ofFloat(1f, values[0]);
            if (Float.isNaN(values[0])) {
                badValue = true;
            }
        } else {
            keyframes[0] = (FloatKeyframe) Keyframe.ofFloat(0f, values[0]);
            for (int i = 1; i < numKeyframes; ++i) {
                keyframes[i] =
                        (FloatKeyframe) Keyframe.ofFloat((float) i / (numKeyframes - 1), values[i]);
                if (Float.isNaN(values[i])) {
                    badValue = true;
                }
            }
        }
        if (badValue) {
            Log.w("Animator", "Bad value (NaN) in float animator");
        }
        return new FloatKeyframeSet(keyframes);
    }

把我们传进来的可变参数封装成帧数组

FloatKeyframe keyframes[]
,只有1个参数则它会帮你设置起始帧。封装成数组后在最后调用了
FloatKeyframeSet(keyframes);
实例化FloatKeyframeSet并返回。
回到了PropertyValuesHolder设置到全局变量
mKeyframes = KeyframeSet.ofFloat(values);

然后又设置到了FloatPropertyValuesHolder下全局变量
mFloatKeyframes = (Keyframes.FloatKeyframes) mKeyframes;

以上总的来说就是

PropertyValuesHolder.ofFloat(mProperty, values)
执行后把参数们设置到了FloatPropertyValuesHolder下然后封装成帧数组返回

然后

setValues(PropertyValuesHolder.ofFloat(mProperty, values));

看下setValues()干了什么

public void setValues(PropertyValuesHolder... values) {
        int numValues = values.length;
        mValues = values;
        mValuesMap = new HashMap(numValues);
        for (int i = 0; i < numValues; ++i) {
            PropertyValuesHolder valuesHolder = values[i];
            mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder);
        }
        // New property/values/target should cause re-initialization prior to starting
        mInitialized = false;
    }

到这我们的

ObjectAnimator.ofFloat(textView,"scale", 0f, 1f)
这句话就完毕了,并拿到ObjectAnimator对象

然后我们自己设置了插值器啊,动画执行时间啊,没啥说的,都是设置操作,

然后我们调用

ObjectAnimator.start()
开启动画方法,关键来了啊:
点进去来到

 @Override
    public void start() {
        AnimationHandler.getInstance().autoCancelBasedOn(this);//如果之前还在动画运行就取消掉之前动画
        if (DBG) {
            Log.d(LOG_TAG, "Anim target, duration: " + getTarget() + ", " + getDuration());
            for (int i = 0; i < mValues.length; ++i) {
                PropertyValuesHolder pvh = mValues[i];
                Log.d(LOG_TAG, "   Values[" + i + "]: " +
                    pvh.getPropertyName() + ", " + pvh.mKeyframes.getValue(0) + ", " +
                    pvh.mKeyframes.getValue(1));
            }
        }
        super.start();
    }

调用了

super.start()
方法,一看就是父类ValueAnimator的start()方法

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) {
                // 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;
        // Resets mLastFrameTime when start() is called, so that if the animation was running,
        // calling start() would put the animation in the
        // started-but-not-yet-reached-the-first-frame phase.
        mLastFrameTime = -1;
        mFirstFrameTime = -1;
        mStartTime = -1;
        addAnimationCallback(0);
        if (mStartDelay == 0 || mSeekFraction >= 0 || mReversing) {
            // If there's no start delay, init the animation and notify start listeners right away
            // to be consistent with the previous behavior. Otherwise, postpone this until the first
            // frame after the start delay.
            startAnimation();
            if (mSeekFraction == -1) {
                // No seek, start at play time 0. Note that the reason we are not using fraction 0
                // is because for animations with 0 duration, we want to be consistent with pre-N
                // behavior: skip to the final value immediately.
                setCurrentPlayTime(0);
            } else {
                setCurrentFraction(mSeekFraction);
            }
        }
    }

重要看27行调用了

addAnimationCallback(0);

private void addAnimationCallback(long delay) {
        if (!mSelfPulse) {
            return;
        }
        getAnimationHandler().addAnimationFrameCallback(this, delay);
    }

getAnimationHandler():

public AnimationHandler getAnimationHandler() {
        return AnimationHandler.getInstance();
    }

拿到对象后后调用了

AnimationHandleraddAnimationFrameCallback()
方法,传进了本类对象,和执行延迟时间:

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));
        }
    }

postFrameCallback从方法名知道,提交了个callback回调对象,也就是说会有其他方法进行调用这个callback回调对象里的函数,什么?这个callback居然就是我们的ValueAnimator,
没错:

public class ValueAnimator extends Animator implements AnimationHandler.AnimationFrameCallback {

ValueAnimator 实现了AnimationHandler.AnimationFrameCallback这个回调类!并实现了会被别人回调的关键方法:

 public final boolean doAnimationFrame(long frameTime) {
        if (mStartTime  0) {
                // Offset by the duration that the animation was paused
                mStartTime += (frameTime - mPauseTime);
            }
        }
        if (!mRunning) {
            // If not running, that means the animation is in the start delay phase of a forward
            // running animation. In the case of reversing, we want to run start delay in the end.
            if (mStartTime > frameTime && mSeekFraction == -1) {
                // This is when no seek fraction is set during start delay. If developers change the
                // seek fraction during the delay, animation will start from the seeked position
                // right away.
                return false;
            } else {
                // If mRunning is not set by now, that means non-zero start delay,
                // no seeking, not reversing. At this point, start delay has passed.
                mRunning = true;
                startAnimation();
            }
        }
        if (mLastFrameTime = 0) {
                long seekTime = (long) (getScaledDuration() * mSeekFraction);
                mStartTime = frameTime - seekTime;
                mSeekFraction = -1;
            }
            mStartTimeCommitted = false; // allow start time to be compensated for jank
        }
        mLastFrameTime = frameTime;
        // The frame time might be before the start time during the first frame of
        // an animation.  The "current time" must always be on or after the start
        // time to avoid animating frames at negative time intervals.  In practice, this
        // is very rare and only happens when seeking backwards.
        final long currentTime = Math.max(frameTime, mStartTime);
        boolean finished = animateBasedOnTime(currentTime);
        if (finished) {
            endAnimation();
        }
        return finished;
    }

doAnimationFrame()非常关键的一个方法,由android的Vsnyc进行每16毫秒进行调用一次
这个函数做了一系列动画生命周期的东西
最重要的是调用了

boolean finished = animateBasedOnTime(currentTime);

boolean animateBasedOnTime(long currentTime) {
        boolean done = false;
        if (mRunning) {
            final long scaledDuration = getScaledDuration();
            final float fraction = scaledDuration > 0 ?
                    (float)(currentTime - mStartTime) / scaledDuration : 1f;
            final float lastFraction = mOverallFraction;
            final boolean newIteration = (int) fraction > (int) lastFraction;
            final boolean lastIterationFinished = (fraction >= mRepeatCount + 1) &&
                    (mRepeatCount != INFINITE);
            if (scaledDuration == 0) {
                // 0 duration animator, ignore the repeat count and skip to the end
                done = true;
            } else if (newIteration && !lastIterationFinished) {
                // Time to repeat
                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);
            float currentIterationFraction = getCurrentIterationFraction(
                    mOverallFraction, mReversing);
            animateValue(currentIterationFraction);
        }
        return done;
    }

在第5行算出动画执行百分比,也就是每一帧都会不一样
第19行回调重复的监听
在下一行animateValue(currentIterationFraction);,这个animateValue(currentIterationFraction)方法子类也有实现,所以肯定会先调用子类的
看看子类的执行了什么

 void animateValue(float fraction) {
        final Object target = getTarget();
        if (mTarget != null && target == null) {//如果我们每设置对应控件直接取消动画返回
            // We lost the target reference, cancel and clean up. Note: we allow null target if the
            /// target has never been set.
            cancel();
            return;
        }
        super.animateValue(fraction);
        int numValues = mValues.length;
        for (int i = 0; i < numValues; ++i) {
            mValues[i].setAnimatedValue(target);
        }
    }

第九行又去调用父类的

animateValue()
方法

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);//调用我们写的监听器,把当前对象传进去
            }
        }
    }

第二行利用传进来的百分比调用插值器获取动画速率
第三行 赋值给成员变量
第五行 还记得吗mValues就是哪个FloatPropertyValuesHolder对象同时也是继承于
PropertyValuesHolder对象,所以去看里面的calculateValue()方法

void calculateValue(float fraction) {
        Object value = mKeyframes.getValue(fraction);
        mAnimatedValue = mConverter == null ? value : mConverter.convert(value);
    }

mKeyframes是我们之前设置的帧集合,调用getValue()
我们找啊找来到FloatKeyframeset下的getValue():

@Override
    public float getFloatValue(float fraction) {
        if (fraction = 1f) {
            final FloatKeyframe prevKeyframe = (FloatKeyframe) mKeyframes.get(mNumKeyframes - 2);
            final FloatKeyframe nextKeyframe = (FloatKeyframe) mKeyframes.get(mNumKeyframes - 1);
            float prevValue = prevKeyframe.getFloatValue();
            float nextValue = nextKeyframe.getFloatValue();
            float prevFraction = prevKeyframe.getFraction();
            float nextFraction = nextKeyframe.getFraction();
            final TimeInterpolator interpolator = nextKeyframe.getInterpolator();
            if (interpolator != null) {
                fraction = interpolator.getInterpolation(fraction);
            }
            float intervalFraction = (fraction - prevFraction) / (nextFraction - prevFraction);
            return mEvaluator == null ?
                    prevValue + intervalFraction * (nextValue - prevValue) :
                    ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)).
                            floatValue();
        }
        FloatKeyframe prevKeyframe = (FloatKeyframe) mKeyframes.get(0);
        for (int i = 1; i < mNumKeyframes; ++i) {
            FloatKeyframe nextKeyframe = (FloatKeyframe) mKeyframes.get(i);
            if (fraction < nextKeyframe.getFraction()) {
                final TimeInterpolator interpolator = nextKeyframe.getInterpolator();
                float intervalFraction = (fraction - prevKeyframe.getFraction()) /
                    (nextKeyframe.getFraction() - prevKeyframe.getFraction());
                float prevValue = prevKeyframe.getFloatValue();
                float nextValue = nextKeyframe.getFloatValue();
                // Apply interpolator on the proportional duration.
                if (interpolator != null) {
                    intervalFraction = interpolator.getInterpolation(intervalFraction);
                }
                return mEvaluator == null ?
                        prevValue + intervalFraction * (nextValue - prevValue) :
                        ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)).
                            floatValue();
            }
            prevKeyframe = nextKeyframe;
        }
        // shouldn't get here
        return ((Number)mKeyframes.get(mNumKeyframes - 1).getValue()).floatValue();
    }

就是用fration和插值器和估值器算Vaule值啦,有没有成就感?
返回后在calculateValue里被赋值到了全局变量mAnimatedValue
我们去看看我们平常用的getAnimatedValue()方法把:

Object getAnimatedValue() {
        return mAnimatedValue;
    }


不过这还没完
这只是super.animatedValue()的调用完成
继续看下面

@Override
    void animateValue(float fraction) {
        final Object target = getTarget();
        if (mTarget != null && target == null) {
            // We lost the target reference, cancel and clean up. Note: we allow null target if the
            /// target has never been set.
            cancel();
            return;
        }
        super.animateValue(fraction);
        int numValues = mValues.length;
        for (int i = 0; i < numValues; ++i) {
            mValues[i].setAnimatedValue(target);
        }
    }

有个循环不断进行

mValues[i].setAnimatedValue(target);

这就是如果我们由target控件,就自行帮我们设值!
去看看,它咱们拿到咱们要设置的属性吧:点击来到PropertyValueHolder下的:

void setAnimatedValue(Object target) {
            if (mIntProperty != null) {
                mIntProperty.setValue(target, mIntAnimatedValue);
                return;
            }
            if (mProperty != null) {
                mProperty.set(target, mIntAnimatedValue);
                return;
            }
            if (mJniSetter != 0) {
                nCallIntMethod(target, mJniSetter, mIntAnimatedValue);
                return;
            }
            if (mSetter != null) {
                try {
                    mTmpValueArray[0] = mIntAnimatedValue;//获取之前全局变量mAnimatedValue
                    mSetter.invoke(target, mTmpValueArray);
                } catch (InvocationTargetException e) {
                    Log.e("PropertyValuesHolder", e.toString());
                } catch (IllegalAccessException e) {
                    Log.e("PropertyValuesHolder", e.toString());
                }
            }
        }

这楼里mSetter一般程序没有错误的话都有值,那这个值在哪设置的呢?
我们先跳出上面的过程
回到start()方法来:这是ValueAnimator下的

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) {
                // 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;
        // Resets mLastFrameTime when start() is called, so that if the animation was running,
        // calling start() would put the animation in the
        // started-but-not-yet-reached-the-first-frame phase.
        mLastFrameTime = -1;
        mFirstFrameTime = -1;
        mStartTime = -1;
        addAnimationCallback(0);
        if (mStartDelay == 0 || mSeekFraction >= 0 || mReversing) {
            // If there's no start delay, init the animation and notify start listeners right away
            // to be consistent with the previous behavior. Otherwise, postpone this until the first
            // frame after the start delay.
            startAnimation();
            if (mSeekFraction == -1) {
                // No seek, start at play time 0. Note that the reason we are not using fraction 0
                // is because for animations with 0 duration, we want to be consistent with pre-N
                // behavior: skip to the final value immediately.
                setCurrentPlayTime(0);
            } else {
                setCurrentFraction(mSeekFraction);
            }
        }
    }

我们发现在倒数11行调用了startAnimation();,问题来了,我们之前 addAnimationCallback(0);不是已经在运行动画了吗?其实从方法名和之前讲的就已经知道了addAnimationCallback就是添加回调,执行还得看android的Vsync的信号,这里注释也说明白了,如果这个动画不是延时动画,在第一帧的时候并不会有效果,第二帧才会有,因为得等startAnimation()获取setter这个东东。为什么,现在来点进去看看吧:

private void startAnimation() {
        if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
            Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, getNameForTrace(),
                    System.identityHashCode(this));
        }
        mAnimationEndRequested = false;
        initAnimation();
        mRunning = true;
        if (mSeekFraction >= 0) {
            mOverallFraction = mSeekFraction;
        } else {
            mOverallFraction = 0f;
        }
        if (mListeners != null) {
            notifyStartListeners();
        }
    }

主要执行了 initAnimation();这个方法,
我们发现子类ObjectAnimator中还会有 initAnimation()同名方法,毫无疑问先执行子类的咯:

void initAnimation() {
        if (!mInitialized) {
            // mValueType may change due to setter/getter setup; do this before calling super.init(),
            // which uses mValueType to set up the default type evaluator.
            final Object target = getTarget();
            if (target != null) {
                final int numValues = mValues.length;
                for (int i = 0; i < numValues; ++i) {
                    mValues[i].setupSetterAndGetter(target);
                }
            }
            super.initAnimation();
        }
    }

第九行调用PropertyValueHolder的

setupSetterAndGetter(target)
;

@Override
       void setupSetterAndGetter(Object target) {
        if (mProperty != null) {
            // check to make sure that mProperty is on the class of target
            try {
                Object testValue = null;
                List keyframes = mKeyframes.getKeyframes();
                int keyframeCount = keyframes == null ? 0 : keyframes.size();
                for (int i = 0; i < keyframeCount; i++) {
                    Keyframe kf = keyframes.get(i);
                    if (!kf.hasValue() || kf.valueWasSetOnStart()) {
                        if (testValue == null) {
                            testValue = convertBack(mProperty.get(target));
                        }
                        kf.setValue(testValue);
                        kf.setValueWasSetOnStart(true);
                    }
                }
                return;
            } catch (ClassCastException e) {
                Log.w("PropertyValuesHolder","No such property (" + mProperty.getName() +
                        ") on target object " + target + ". Trying reflection instead");
                mProperty = null;
            }
        }
        // We can't just say 'else' here because the catch statement sets mProperty to null.
        if (mProperty == null) {
            Class targetClass = target.getClass();
            if (mSetter == null) {
                setupSetter(targetClass);
            }
            List keyframes = mKeyframes.getKeyframes();
            int keyframeCount = keyframes == null ? 0 : keyframes.size();
            for (int i = 0; i < keyframeCount; i++) {
                Keyframe kf = keyframes.get(i);
                if (!kf.hasValue() || kf.valueWasSetOnStart()) {
                    if (mGetter == null) {
                        setupGetter(targetClass);
                        if (mGetter == null) {
                            // Already logged the error - just return to avoid NPE
                            return;
                        }
                    }
                    try {
                        Object value = convertBack(mGetter.invoke(target));
                        kf.setValue(value);
                        kf.setValueWasSetOnStart(true);
                    } catch (InvocationTargetException e) {
                        Log.e("PropertyValuesHolder", e.toString());
                    } catch (IllegalAccessException e) {
                        Log.e("PropertyValuesHolder", e.toString());
                    }
                }
            }
        }
    }

第29行mSetter 为空时调用

setupSetter(target.getClass());

void setupSetter(Class targetClass) {
        Class propertyType = mConverter == null ? mValueType : mConverter.getTargetType();
        mSetter = setupSetterOrGetter(targetClass, sSetterPropertyMap, "set", propertyType);
    }

在第3行

mSetter = setupSetterOrGetter(targetClass, sSetterPropertyMap, "set", propertyType);

传入

targetClass,我们的控件类字节码对象 sSetterPropertyMap 这个字节码对象下用于保存所有的set开头函数的Map “set” set方法前面的名字 propertyType 参数类型

进去看

private Method setupSetterOrGetter(Class targetClass,
            HashMap<Class, HashMap> propertyMapMap,
            String prefix, Class valueType) {
        Method setterOrGetter = null;
        synchronized(propertyMapMap) {
            // Have to lock property map prior to reading it, to guard against
            // another thread putting something in there after we've checked it
            // but before we've added an entry to it
            HashMap propertyMap = propertyMapMap.get(targetClass);
            boolean wasInMap = false;
            if (propertyMap != null) {
                wasInMap = propertyMap.containsKey(mPropertyName);
                if (wasInMap) {
                    setterOrGetter = propertyMap.get(mPropertyName);
                }
            }
            if (!wasInMap) {
                setterOrGetter = getPropertyFunction(targetClass, prefix, valueType);
                if (propertyMap == null) {
                    propertyMap = new HashMap();
                    propertyMapMap.put(targetClass, propertyMap);
                }
                propertyMap.put(mPropertyName, setterOrGetter);
            }
        }
        return setterOrGetter;
    }

第十八行

setterOrGetter = getPropertyFunction(targetClass, prefix, valueType);

这里边就是反射获取get和set函数
然后返回返回。
mSetter终于有值了呢,回去吧,话说我们之前是从这跳出来的:

void setAnimatedValue(Object target) {
            if (mIntProperty != null) {
                mIntProperty.setValue(target, mIntAnimatedValue);
                return;
            }
            if (mProperty != null) {
                mProperty.set(target, mIntAnimatedValue);
                return;
            }
            if (mJniSetter != 0) {
                nCallIntMethod(target, mJniSetter, mIntAnimatedValue);
                return;
            }
            if (mSetter != null) {
                try {
                    mTmpValueArray[0] = mIntAnimatedValue;
                    mSetter.invoke(target, mTmpValueArray);
                } catch (InvocationTargetException e) {
                    Log.e("PropertyValuesHolder", e.toString());
                } catch (IllegalAccessException e) {
                    Log.e("PropertyValuesHolder", e.toString());
                }
            }
        }

第十七行就用这个invoke(调用的意思):mSetter.invoke(target, mTmpValueArray);设置控件value了
终于没了呀

总结: ObjectAnimatior.ofFloat()进行一系列初始化,比如KeyframeSet,设置target控件,返回ObjectAnimatior对象。 然后由我们继续设置插值器,估值器啊什么的。 初始化完成后start()开始,初始化回调类然后提交回调,也就是ObjectAnimatior本身,因为实现了回调类。 android会由Vsync信号每隔16ms调用一次这个回调类下的回调方法。 设置好回调后,紧接着就会反射去获取get和set方法。 信号一来,回调方法就会计算当前时间和开始时间这段时间动画的百分比啊。
然后放到KeyFrameSet里和估值器,插值器,动画开始和结束帧,求得当前动画属性值 最后就是用反射获取到的方法进行设值啦
作者:Eliza白


--结束END--

本文标题: Android动画(四)动画框架源码分析

本文链接: https://www.lsjlt.com/news/29414.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作