循环 AnimationSet 会导致 StackOverflowError

Looping an AnimationSet causes StackOverflowError

我正在删除一个 android 应用程序,其中有一个无限重复的动画导致 WhosebugError。当同一对象上的另一个动画开始时,它会执行此操作。

private fun pulse() {
    val randomGenerator = Random()

    val durationx = randomGenerator.nextInt(4000) + 1500

    val inflateX = ObjectAnimator.ofFloat(mContentView, "scaleX", 1.3f).apply {
        duration = durationx.toLong()
    }
    val inflateY = ObjectAnimator.ofFloat(mContentView, "scaleY", 1.3f).apply {
        duration = durationx.toLong()
    }
    val deflateX = ObjectAnimator.ofFloat(mContentView, "scaleX", 1.0f).apply {
        duration = durationx.toLong()
    }
    val deflateY = ObjectAnimator.ofFloat(mContentView, "scaleY", 1.0f).apply {
        duration = durationx.toLong()
    }
    val rotate = ObjectAnimator.ofFloat(mContentView, "rotation", 1.0f).apply {
        duration = durationx.toLong()
    }
    val soulToButton = AnimatorSet().apply {
        play(inflateX).with(inflateY)
        play(rotate).with(inflateX)
        play(deflateX).after(inflateX)
        play(deflateY).after(inflateY)
        start()
    }

    soulToButton.addListener(object: AnimatorListenerAdapter() {
        override fun onAnimationEnd(animation: Animator) {
            super.onAnimationEnd(animation)
            soulToButton.start() // stacktrace points to this line as cause for the error.
        }
    })
    soulToButton.start()

    AnimatorSet().apply {
        play(soulToButton)
        start()
    }
}

我尝试将函数更改为 fun pulse(stop: boolean),在其他动画开始之前调用 pulse(false) 来启动脉冲和 pulse(true),并在几个地方添加 if (stop) {soulToButton.cancel()}。我还尝试换行导致这样的错误:while(stop == false){soultoButton.start()}

所有这些都没有帮助。

它是 Kotlin,但它仍然是 Java,所有 JVM 限制都与此相关。因此,由于 JVM 堆栈有限,您不能无限期地调用一个函数而不会导致 WhosebugError。

有一些特殊功能可以帮助您无限期地 运行 动画。例如

objectAnimator.setRepeatCount(ObjectAnimator.INFINITE);

或者你的情况

ObjectAnimator.ofFloat(mContentView, "scaleX", 1.3f).apply {
        duration = durationx.toLong()
        repeatCount = ObjectAnimator.INFINITE
    }

以相同方式修改所有动画并将它们链接到 AnimatorSet 后,其 start 函数将无限期播放此动画,而不会发生 WhosebugError。

希望对您有所帮助。

您正在尝试在此处完成后再次开始动画,

soulToButton.addListener(object: AnimatorListenerAdapter() {
        override fun onAnimationEnd(animation: Animator) {
            super.onAnimationEnd(animation)
            soulToButton.start() // This will start the animation again without an end to the animation hence the Whosebug error.
        }
    })

为了运行一个无限时间的动画使用下面的代码,

val inflateX = ObjectAnimator.ofFloat(mContentView, "scaleX", 1.3f).apply {
        duration = durationx.toLong()
        repeatCount = ObjectAnimator.INFINITE
        }

val soulToButton = AnimatorSet().apply {
        play(inflateX).with(inflateY)
        play(rotate).with(inflateX)
        play(deflateX).after(inflateX)
        play(deflateY).after(inflateY)

    }

soulToButton.start()

试试这个版本:它简短明了,基本上做同样的事情。

    val randomGenerator = Random()

    val durationx = randomGenerator.nextInt(4000) + 1500

    val animator = animator@{ property : String, value : Float ->
        return@animator ObjectAnimator.ofFloat(mContextView, property, value).apply {
            duration = durationx.toLong()
            repeatMode = REVERSE
            repeatCount = INFINITE
        }
    }

    AnimatorSet().apply {
        playTogether(animator("scaleX", 1.3f),animator("scaleY", 1.3f),animator("rotation", 45.0f))
        start()
    }