am 14c43689: Merge "Fix issue with RNA destruction mid-animation" into lmp-mr1-dev
* commit '14c436897ca56800a3758008f0631c559a898967': Fix issue with RNA destruction mid-animation
This commit is contained in:
@@ -148,6 +148,10 @@ public class RenderNodeAnimator extends Animator {
|
|||||||
if (mState != STATE_PREPARE) {
|
if (mState != STATE_PREPARE) {
|
||||||
throw new IllegalStateException("Animator has already started, cannot change it now!");
|
throw new IllegalStateException("Animator has already started, cannot change it now!");
|
||||||
}
|
}
|
||||||
|
if (mNativePtr == null) {
|
||||||
|
throw new IllegalStateException("Animator's target has been destroyed "
|
||||||
|
+ "(trying to modify an animation after activity destroy?)");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean isNativeInterpolator(TimeInterpolator interpolator) {
|
static boolean isNativeInterpolator(TimeInterpolator interpolator) {
|
||||||
@@ -180,7 +184,10 @@ public class RenderNodeAnimator extends Animator {
|
|||||||
mState = STATE_DELAYED;
|
mState = STATE_DELAYED;
|
||||||
applyInterpolator();
|
applyInterpolator();
|
||||||
|
|
||||||
if (mStartDelay <= 0 || !mUiThreadHandlesDelay) {
|
if (mNativePtr == null) {
|
||||||
|
// It's dead, immediately cancel
|
||||||
|
cancel();
|
||||||
|
} else if (mStartDelay <= 0 || !mUiThreadHandlesDelay) {
|
||||||
nSetStartDelay(mNativePtr.get(), mStartDelay);
|
nSetStartDelay(mNativePtr.get(), mStartDelay);
|
||||||
doStart();
|
doStart();
|
||||||
} else {
|
} else {
|
||||||
@@ -208,7 +215,9 @@ public class RenderNodeAnimator extends Animator {
|
|||||||
|
|
||||||
private void moveToRunningState() {
|
private void moveToRunningState() {
|
||||||
mState = STATE_RUNNING;
|
mState = STATE_RUNNING;
|
||||||
nStart(mNativePtr.get(), this);
|
if (mNativePtr != null) {
|
||||||
|
nStart(mNativePtr.get());
|
||||||
|
}
|
||||||
notifyStartListeners();
|
notifyStartListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,7 +236,6 @@ public class RenderNodeAnimator extends Animator {
|
|||||||
getHelper().removeDelayedAnimation(this);
|
getHelper().removeDelayedAnimation(this);
|
||||||
moveToRunningState();
|
moveToRunningState();
|
||||||
}
|
}
|
||||||
nEnd(mNativePtr.get());
|
|
||||||
|
|
||||||
final ArrayList<AnimatorListener> listeners = cloneListeners();
|
final ArrayList<AnimatorListener> listeners = cloneListeners();
|
||||||
final int numListeners = listeners == null ? 0 : listeners.size();
|
final int numListeners = listeners == null ? 0 : listeners.size();
|
||||||
@@ -235,10 +243,7 @@ public class RenderNodeAnimator extends Animator {
|
|||||||
listeners.get(i).onAnimationCancel(this);
|
listeners.get(i).onAnimationCancel(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mViewTarget != null) {
|
end();
|
||||||
// Kick off a frame to flush the state change
|
|
||||||
mViewTarget.invalidateViewProperty(true, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,11 +254,16 @@ public class RenderNodeAnimator extends Animator {
|
|||||||
getHelper().removeDelayedAnimation(this);
|
getHelper().removeDelayedAnimation(this);
|
||||||
doStart();
|
doStart();
|
||||||
}
|
}
|
||||||
|
if (mNativePtr != null) {
|
||||||
nEnd(mNativePtr.get());
|
nEnd(mNativePtr.get());
|
||||||
if (mViewTarget != null) {
|
if (mViewTarget != null) {
|
||||||
// Kick off a frame to flush the state change
|
// Kick off a frame to flush the state change
|
||||||
mViewTarget.invalidateViewProperty(true, false);
|
mViewTarget.invalidateViewProperty(true, false);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// It's already dead, jump to onFinish
|
||||||
|
onFinished();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,9 +291,11 @@ public class RenderNodeAnimator extends Animator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setTarget(RenderNode node) {
|
private void setTarget(RenderNode node) {
|
||||||
|
checkMutable();
|
||||||
if (mTarget != null) {
|
if (mTarget != null) {
|
||||||
throw new IllegalStateException("Target already set!");
|
throw new IllegalStateException("Target already set!");
|
||||||
}
|
}
|
||||||
|
nSetListener(mNativePtr.get(), this);
|
||||||
mTarget = node;
|
mTarget = node;
|
||||||
mTarget.addAnimator(this);
|
mTarget.addAnimator(this);
|
||||||
}
|
}
|
||||||
@@ -346,6 +358,12 @@ public class RenderNodeAnimator extends Animator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void onFinished() {
|
protected void onFinished() {
|
||||||
|
if (mState == STATE_PREPARE) {
|
||||||
|
// Unlikely but possible, the native side has been destroyed
|
||||||
|
// before we have started.
|
||||||
|
releaseNativePtr();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (mState == STATE_DELAYED) {
|
if (mState == STATE_DELAYED) {
|
||||||
getHelper().removeDelayedAnimation(this);
|
getHelper().removeDelayedAnimation(this);
|
||||||
notifyStartListeners();
|
notifyStartListeners();
|
||||||
@@ -361,9 +379,15 @@ public class RenderNodeAnimator extends Animator {
|
|||||||
// Release the native object, as it has a global reference to us. This
|
// Release the native object, as it has a global reference to us. This
|
||||||
// breaks the cyclic reference chain, and allows this object to be
|
// breaks the cyclic reference chain, and allows this object to be
|
||||||
// GC'd
|
// GC'd
|
||||||
|
releaseNativePtr();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void releaseNativePtr() {
|
||||||
|
if (mNativePtr != null) {
|
||||||
mNativePtr.release();
|
mNativePtr.release();
|
||||||
mNativePtr = null;
|
mNativePtr = null;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private ArrayList<AnimatorListener> cloneListeners() {
|
private ArrayList<AnimatorListener> cloneListeners() {
|
||||||
@@ -484,7 +508,8 @@ public class RenderNodeAnimator extends Animator {
|
|||||||
private static native void nSetStartDelay(long nativePtr, long startDelay);
|
private static native void nSetStartDelay(long nativePtr, long startDelay);
|
||||||
private static native void nSetInterpolator(long animPtr, long interpolatorPtr);
|
private static native void nSetInterpolator(long animPtr, long interpolatorPtr);
|
||||||
private static native void nSetAllowRunningAsync(long animPtr, boolean mayRunAsync);
|
private static native void nSetAllowRunningAsync(long animPtr, boolean mayRunAsync);
|
||||||
|
private static native void nSetListener(long animPtr, RenderNodeAnimator listener);
|
||||||
|
|
||||||
private static native void nStart(long animPtr, RenderNodeAnimator finishListener);
|
private static native void nStart(long animPtr);
|
||||||
private static native void nEnd(long animPtr);
|
private static native void nEnd(long animPtr);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -177,9 +177,13 @@ static void setAllowRunningAsync(JNIEnv* env, jobject clazz, jlong animatorPtr,
|
|||||||
animator->setAllowRunningAsync(mayRunAsync);
|
animator->setAllowRunningAsync(mayRunAsync);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void start(JNIEnv* env, jobject clazz, jlong animatorPtr, jobject finishListener) {
|
static void setListener(JNIEnv* env, jobject clazz, jlong animatorPtr, jobject finishListener) {
|
||||||
BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
|
BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
|
||||||
animator->setListener(new AnimationListenerBridge(env, finishListener));
|
animator->setListener(new AnimationListenerBridge(env, finishListener));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void start(JNIEnv* env, jobject clazz, jlong animatorPtr) {
|
||||||
|
BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
|
||||||
animator->start();
|
animator->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,7 +212,8 @@ static JNINativeMethod gMethods[] = {
|
|||||||
{ "nSetStartDelay", "(JJ)V", (void*) setStartDelay },
|
{ "nSetStartDelay", "(JJ)V", (void*) setStartDelay },
|
||||||
{ "nSetInterpolator", "(JJ)V", (void*) setInterpolator },
|
{ "nSetInterpolator", "(JJ)V", (void*) setInterpolator },
|
||||||
{ "nSetAllowRunningAsync", "(JZ)V", (void*) setAllowRunningAsync },
|
{ "nSetAllowRunningAsync", "(JZ)V", (void*) setAllowRunningAsync },
|
||||||
{ "nStart", "(JLandroid/view/RenderNodeAnimator;)V", (void*) start },
|
{ "nSetListener", "(JLandroid/view/RenderNodeAnimator;)V", (void*) setListener},
|
||||||
|
{ "nStart", "(J)V", (void*) start},
|
||||||
{ "nEnd", "(J)V", (void*) end },
|
{ "nEnd", "(J)V", (void*) end },
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -17,12 +17,14 @@
|
|||||||
package com.android.test.hwui;
|
package com.android.test.hwui;
|
||||||
|
|
||||||
import android.animation.Animator;
|
import android.animation.Animator;
|
||||||
|
import android.animation.Animator.AnimatorListener;
|
||||||
import android.animation.AnimatorSet;
|
import android.animation.AnimatorSet;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
import android.view.ViewAnimationUtils;
|
import android.view.ViewAnimationUtils;
|
||||||
@@ -37,6 +39,29 @@ public class RevealActivity extends Activity implements OnClickListener {
|
|||||||
private boolean mShouldBlock;
|
private boolean mShouldBlock;
|
||||||
private int mIteration = 0;
|
private int mIteration = 0;
|
||||||
|
|
||||||
|
private AnimatorListener mListener = new AnimatorListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationStart(Animator animation) {
|
||||||
|
Log.d("Reveal", "onAnimatorStart " + animation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationRepeat(Animator animation) {
|
||||||
|
Log.d("Reveal", "onAnimationRepeat " + animation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
Log.d("Reveal", "onAnimationEnd " + animation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationCancel(Animator animation) {
|
||||||
|
Log.d("Reveal", "onAnimationCancel " + animation);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
@@ -59,6 +84,8 @@ public class RevealActivity extends Activity implements OnClickListener {
|
|||||||
Animator animator = ViewAnimationUtils.createCircularReveal(view,
|
Animator animator = ViewAnimationUtils.createCircularReveal(view,
|
||||||
view.getWidth() / 2, view.getHeight() / 2,
|
view.getWidth() / 2, view.getHeight() / 2,
|
||||||
0, Math.max(view.getWidth(), view.getHeight()));
|
0, Math.max(view.getWidth(), view.getHeight()));
|
||||||
|
Log.d("Reveal", "Calling start...");
|
||||||
|
animator.addListener(mListener);
|
||||||
if (mIteration < 2) {
|
if (mIteration < 2) {
|
||||||
animator.setDuration(DURATION);
|
animator.setDuration(DURATION);
|
||||||
animator.start();
|
animator.start();
|
||||||
@@ -66,6 +93,7 @@ public class RevealActivity extends Activity implements OnClickListener {
|
|||||||
AnimatorSet set = new AnimatorSet();
|
AnimatorSet set = new AnimatorSet();
|
||||||
set.playTogether(animator);
|
set.playTogether(animator);
|
||||||
set.setDuration(DURATION);
|
set.setDuration(DURATION);
|
||||||
|
set.addListener(mListener);
|
||||||
set.start();
|
set.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user