Estoy desarrollando una aplicación de Android en la que tengo una animación que se repite infinitamente que está causando un StackOverflowError. Lo hace cuando se inicia otra animación en el mismo objeto.
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() } } Intenté cambiar la función a fun pulse(stop: boolean) , llamando a pulse(false) para iniciar el pulso y pulse(true) antes de que comience la otra animación, y agregando if (stop) {soulToButton.cancel()} en varios lugares . También intenté envolver la línea que causaba el error así: while(stop == false){soultoButton.start()}
Todo esto no ayudó.
Es Kotlin pero sigue siendo Java y todas las limitaciones de JVM son relevantes aquí. Por lo tanto, no puede llamar a una función indefinidamente sin causar StackOverflowError ya que la pila de JVM es limitada.
Hay funciones especiales que te ayudarán a ejecutar la animación indefinidamente. Por ejemplo
objectAnimator.setRepeatCount(ObjectAnimator.INFINITE);O en tu caso
ObjectAnimator.ofFloat(mContentView, "scaleX", 1.3f).apply { duration = durationx.toLong() repeatCount = ObjectAnimator.INFINITE } Después de modificar todas sus animaciones de la misma manera y encadenarlas en AnimatorSet , su función de start reproducirá esta animación por tiempo indefinido sin StackOverflowError.
Espero eso ayude.
Pruebe esta versión: es corta y concisa y básicamente hace lo mismo.
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() }Está intentando iniciar la animación nuevamente después de que se haya completado aquí,
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. } })Para ejecutar una animación por tiempo infinito, use el siguiente código,
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()