1 package org.robolectric.shadows; 2 3 import static android.os.Build.VERSION_CODES.N; 4 import static org.robolectric.shadow.api.Shadow.directlyOn; 5 6 import android.animation.AnimationHandler; 7 import android.animation.ValueAnimator; 8 import org.robolectric.RuntimeEnvironment; 9 import org.robolectric.annotation.Implementation; 10 import org.robolectric.annotation.Implements; 11 import org.robolectric.annotation.RealObject; 12 import org.robolectric.annotation.Resetter; 13 import org.robolectric.util.ReflectionHelpers; 14 15 @Implements(ValueAnimator.class) 16 public class ShadowValueAnimator { 17 18 @RealObject 19 private ValueAnimator realObject; 20 21 private int actualRepeatCount; 22 23 @Resetter 24 public static void reset() { 25 /* ValueAnimator.sAnimationHandler is a static thread local that otherwise would survive between 26 * tests. The AnimationHandler.mAnimationScheduled is set to true when the scheduleAnimation() is 27 * called and the reset to false when run() is called by the Choreographer. If an animation is 28 * already scheduled, it will not post to the Choreographer. This is a problem if a previous 29 * test leaves animations on the Choreographers callback queue without running them as it will 30 * cause the AnimationHandler not to post a callback. We reset the thread local here so a new 31 * one will be created for each test with a fresh state. 32 */ 33 if (RuntimeEnvironment.getApiLevel() >= N) { 34 ThreadLocal<AnimationHandler> animatorHandlerTL = 35 ReflectionHelpers.getStaticField(AnimationHandler.class, "sAnimatorHandler"); 36 animatorHandlerTL.remove(); 37 } else { 38 ReflectionHelpers.callStaticMethod(ValueAnimator.class, "clearAllAnimations"); 39 ThreadLocal<AnimationHandler> animatorHandlerTL = 40 ReflectionHelpers.getStaticField(ValueAnimator.class, "sAnimationHandler"); 41 animatorHandlerTL.remove(); 42 } 43 } 44 45 @Implementation 46 protected void setRepeatCount(int count) { 47 actualRepeatCount = count; 48 if (count == ValueAnimator.INFINITE) { 49 count = 1; 50 } 51 directlyOn(realObject, ValueAnimator.class).setRepeatCount(count); 52 } 53 54 /** 55 * Returns the value that was set as the repeat count. This is otherwise the same 56 * as getRepeatCount(), except when the count was set to infinite. 57 * 58 * @return Repeat count. 59 */ 60 public int getActualRepeatCount() { 61 return actualRepeatCount; 62 } 63 } 64