AnimatorSet Cancel 在 Android 8 和以下版的行为不一致坑

问题背景:

有个动画在 onAnimatorEnd 回调中间接调用了 Animator#cancel。在 Android 8 没有问题,但是在 Android 5, Android 6 等版本出现了下面的递归调用。

java.lang.StackOverflowError: stack size 8MB
    ...
    at android.animation.AnimatorSet.cancel(AnimatorSet.java:340)
    ...
    at android.animation.AnimatorSet.cancel(AnimatorSet.java:340)
    ...
    at android.animation.AnimatorSet.cancel(AnimatorSet.java:340)
    ...
    at android.animation.AnimatorSet.cancel(AnimatorSet.java:340)
    ...
    at android.animation.AnimatorSet.cancel(AnimatorSet.java:340)
    ...
    at android.animation.AnimatorSet.cancel(AnimatorSet.java:340)

发现是 AnimatorSet 造成的问题,AnimatorSet 在 Android 8 和 Android 8 以下对 cancel 方法的实现有区别。

Android 8 及以上 Android 8 以下
回调了 onAnimationCancel 之后,不会再回调 onAnimatioinEnd 回调了 onAnimationCancel 之后,会再回调 onAnimatioinEnd

解决方法:

  • 避免存在 onAnimationEnd 中会调用 cancel 的场景
  • 在 onAnimationEnd 调用之后,移除对应的 listener