Я также столкнулся с этой проблемой, когда я хочу получить getTransformation () для следующей анимации после предыдущей анимации, а затем бесконечный цикл вызывает переполнение стека.
Я проанализировал проблему с исходным кодом Android из GrepCode , с кодами ниже в 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);
}