diff options
| author | 2015-08-27 14:56:30 -0700 | |
|---|---|---|
| committer | 2015-08-27 16:13:48 -0700 | |
| commit | 3dbaae1ef4f221b3626810f4ba19eec068dd6304 (patch) | |
| tree | caf8b0d2304a5545aa1c00d2544277032eeb16a9 | |
| parent | 2916fa11eea3e119b8f24bea4daa861294951813 (diff) | |
Prevents recursive call into end() or cancel()
end() and cancel() in ValueAnimator will trigger onAnimationCancel
or onAnimationEnd callback on its listeners. If additional end()
or cancel() request comes from the callback, a loop will be formed.
Therefore, we need to mark when the end is reuqested so we do not
process end() or cancel() request multiple times during one animation
run, and also effectively terminate the loop.
Bug: 23596652
Change-Id: Iefb69eb8969071b43124c09d7cccbe9ff5ba5dcc
| -rw-r--r-- | core/java/android/animation/ValueAnimator.java | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java index 065631cf29e6..da9a8c8d8900 100644 --- a/core/java/android/animation/ValueAnimator.java +++ b/core/java/android/animation/ValueAnimator.java @@ -185,6 +185,11 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio */ boolean mInitialized = false; + /** + * Flag that tracks whether animation has been requested to end. + */ + private boolean mAnimationEndRequested = false; + // // Backing variables // @@ -915,6 +920,7 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio mStarted = true; mPaused = false; mRunning = false; + mAnimationEndRequested = false; updateScaledDuration(); // in case the scale factor has changed since creation time AnimationHandler animationHandler = AnimationHandler.getInstance(); animationHandler.addAnimationFrameCallback(this, mStartDelay); @@ -930,9 +936,15 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio if (Looper.myLooper() == null) { throw new AndroidRuntimeException("Animators may only be run on Looper threads"); } + + // If end has already been requested, through a previous end() or cancel() call, no-op + // until animation starts again. + if (mAnimationEndRequested) { + return; + } + // Only cancel if the animation is actually running or has been started and is about // to run - // Only notify listeners if the animator has actually started if ((mStarted || mRunning) && mListeners != null) { if (!mRunning) { @@ -1029,9 +1041,14 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio * Called internally to end an animation by removing it from the animations list. Must be * called on the UI thread. */ - private void endAnimation() { + private void endAnimation() { + if (mAnimationEndRequested) { + return; + } AnimationHandler handler = AnimationHandler.getInstance(); handler.removeCallback(this); + + mAnimationEndRequested = true; mPaused = false; if ((mStarted || mRunning) && mListeners != null) { if (!mRunning) { @@ -1256,6 +1273,7 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio anim.mStartListenersCalled = false; anim.mStartTime = 0; anim.mStartTimeCommitted = false; + anim.mAnimationEndRequested = false; anim.mPauseTime = 0; anim.mLastFrameTime = 0; anim.mCurrentFraction = 0; |