循环播放AnimationSet会引起StackOverflowError

时间:2019-03-03 09:34:53

标签: android loops kotlin android-animation stack-overflow

我正在分解一个Android应用,其中我有一个无限重复的动画,这会引起StackOverflowError。当在同一对象上启动另一个动画时,便会执行此操作。

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()}

所有这些都无济于事。

3 个答案:

答案 0 :(得分:3)

尝试使用此版本:它简短明了,基本上在做同样的事情。

    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()
    }

答案 1 :(得分:2)

它是Kotlin,但它仍然是Java,并且所有JVM限制都与此处有关。因此,由于JVM堆栈受到限制,因此不能无限期地调用一个函数而不会引起StackOverflowError。

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

objectAnimator.setRepeatCount(ObjectAnimator.INFINITE);

或者就您而言

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

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

希望有帮助。

答案 2 :(得分:0)

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

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 StackOverflow 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()