前のアニメーションが完了した後に次のアニメーションの getTransformation() を実行したい場合にも、この問題に遭遇しました。その後、無限ループがスタックオーバーフローを引き起こします。
Android のソース コードの問題をGrepCodeから分析したところ、以下のコードで、場所呼び出しのみが trueに設定されるためgetTransformation()
、無限ループを引き起こす問題は見つかりませんでし た。次回 を呼び出すと、 によってブロックされるはずですが、そうではありません。onAnimationEnd()
mEnded
getTransformation()
if(!mEnded)
if (expired) {
if (mRepeatCount == mRepeated) {
if (!mEnded) {
mEnded = true; //this is not real!!!
if (mListener != null) {
mListener.onAnimationEnd(this);
}
}
} else {
if (mRepeatCount > 0) {
mRepeated++;
}
if (mRepeatMode == REVERSE) {
mCycleFlip = !mCycleFlip;
}
mStartTime = -1;
mMore = true;
if (mListener != null) {
mListener.onAnimationRepeat(this);
}
}
}
このコード セグメントでは、grepcode が正しくありません。真実は、呼び出さeEnded = true
れた後に設定されることです:onAnimationEnd()
if (!mEnded) {
if (mListener != null) {
mListener.onAnimationEnd(this);
}
//it happen after onAnimationEnd(). cancel() is also does as this
mEnded = true;
}
これで、無限ループが発生する理由が説明できるはずです。animation.hasEnded()
mEnded を true に設定することができなかったため、チェックしても役に立ちません。
この問題をハッキングする方法は次のとおりです。
リスナーにフラグを設定してガードします。
boolean needBlock = false;
public void onAnimationEnd(Animation animation)
{
if ( needBlock ) return;
needBlock = true;
Transformation t= new Transformation();
animation.getTransformation(animation.getDuration(), t);
}
AnimationListner をクリアします。必要に応じて、後で戻すことができます
public void onAnimationEnd(Animation animation)
{
animation.setAnimationListener(null);
Transformation t= new Transformation();
animation.getTransformation(animation.getDuration(), t);
animation.setAnimationListener(this);
}