CancellableContinuation 的 invokeOnCancellation 处理程序中出现异常
Exception in invokeOnCancellation handler for CancellableContinuation
我有一个 suspendCancellableCoroutine 作为动画侦听器扩展,但它在 api 30 时崩溃,这是扩展
suspend fun Animator.startAndWait() = suspendCancellableCoroutine<Unit> { continuation ->
continuation.invokeOnCancellation { cancel() }
this.addListener(object : AnimatorListenerAdapter() {
private var endedSuccessfully = true
override fun onAnimationCancel(animation: Animator?) {
endedSuccessfully = false
}
override fun onAnimationStart(animation: Animator?) {
animation?.removeListener(this)
if (continuation.isActive) {
// If the coroutine is still active...
if (endedSuccessfully) {
// ...and the Animator ended successfully, resume the coroutine
continuation.resume(Unit)
} else {
// ...and the Animator was cancelled, cancel the coroutine too
continuation.cancel()
}
}
}
})
start()
}
我是从另一个动画师的 运行 方法中调用它的
private fun createRevealAnimation() {
val x: Int = binding.root.right / 2
val y: Int = binding.root.bottom - binding.root.bottom / 9
val endRadius = hypot(binding.root.width.toDouble(), binding.root.height.toDouble()).toInt()
viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Default) {
createCircleRevealAnimator(x, y, endRadius).run {
duration = 250
withContext(Dispatchers.Main){
binding.pokeballOpen.visibility = View.VISIBLE
}
startAndWait()
navigateToListFragment()
}
}
}
private fun createCircleRevealAnimator(x: Int, y: Int, endRadius: Int): Animator {
return ViewAnimationUtils.createCircularReveal(
binding.pokeballOpen, x, y,
0f,
endRadius.toFloat()
)
}
在 api 30 之前它在每个版本上都运行良好,然后崩溃并抛出此错误
2021-02-06 17:50:42.205 29495-29590/com.sealstudios.pokemonApp.paid E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-1
Process: com.sealstudios.pokemonApp.paid, PID: 29495
kotlinx.coroutines.CompletionHandlerException: Exception in invokeOnCancellation handler for CancellableContinuation(DispatchedContinuation[Dispatchers.Default, Continuation at com.sealstudios.pokemonApp.ui.SplashScreenFragment$createRevealAnimation.invokeSuspend(SplashScreenFragment.kt:61)@472a1ed]){CancelledContinuation[kotlinx.coroutines.JobCancellationException: StandaloneCoroutine is cancelling; job=StandaloneCoroutine{Cancelling}@c735822]}@e4312b3
at kotlinx.coroutines.CancellableContinuationImpl.callCancelHandler(CancellableContinuationImpl.kt:583)
at kotlinx.coroutines.CancellableContinuationImpl.cancel(CancellableContinuationImpl.kt:195)
at kotlinx.coroutines.CancellableContinuationImpl.parentCancelled$kotlinx_coroutines_core(CancellableContinuationImpl.kt:205)
at kotlinx.coroutines.ChildContinuation.invoke(JobSupport.kt:1484)
at kotlinx.coroutines.JobSupport.notifyCancelling(JobSupport.kt:1511)
at kotlinx.coroutines.JobSupport.tryMakeCompletingSlowPath(JobSupport.kt:897)
at kotlinx.coroutines.JobSupport.tryMakeCompleting(JobSupport.kt:860)
at kotlinx.coroutines.JobSupport.makeCompletingOnce$kotlinx_coroutines_core(JobSupport.kt:825)
at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:111)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:738)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
Caused by: java.lang.IllegalStateException: The current thread must have a looper!
at android.view.Choreographer.initialValue(Choreographer.java:111)
at android.view.Choreographer.initialValue(Choreographer.java:106)
at java.lang.ThreadLocal.setInitialValue(ThreadLocal.java:180)
at java.lang.ThreadLocal.get(ThreadLocal.java:170)
at android.view.Choreographer.getInstance(Choreographer.java:288)
at android.graphics.animation.RenderNodeAnimator$DelayedAnimationHelper.<init>(RenderNodeAnimator.java:431)
at android.graphics.animation.RenderNodeAnimator.getHelper(RenderNodeAnimator.java:415)
at android.graphics.animation.RenderNodeAnimator.cancel(RenderNodeAnimator.java:226)
at com.sealstudios.pokemonApp.ui.listenerExtensions.AnimatorListenersKt$startAndWait$$inlined$suspendCancellableCoroutine$lambda.invoke(AnimatorListeners.kt:12)
at com.sealstudios.pokemonApp.ui.listenerExtensions.AnimatorListenersKt$startAndWait$$inlined$suspendCancellableCoroutine$lambda.invoke(Unknown Source:2)
at kotlinx.coroutines.InvokeOnCancel.invoke(CancellableContinuationImpl.kt:539)
at kotlinx.coroutines.CancellableContinuationImpl.callCancelHandler(CancellableContinuationImpl.kt:230)
at kotlinx.coroutines.CancellableContinuationImpl.cancel(CancellableContinuationImpl.kt:195)
at kotlinx.coroutines.CancellableContinuationImpl.parentCancelled$kotlinx_coroutines_core(CancellableContinuationImpl.kt:205)
at kotlinx.coroutines.ChildContinuation.invoke(JobSupport.kt:1484)
at kotlinx.coroutines.JobSupport.notifyCancelling(JobSupport.kt:1511)
at kotlinx.coroutines.JobSupport.tryMakeCompletingSlowPath(JobSupport.kt:897)
at kotlinx.coroutines.JobSupport.tryMakeCompleting(JobSupport.kt:860)
at kotlinx.coroutines.JobSupport.makeCompletingOnce$kotlinx_coroutines_core(JobSupport.kt:825)
at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:111)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:738)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
任何人都有任何想法我对这个很迷茫。
删除Dispatchers.Default
viewLifecycleOwner.lifecycleScope.launch { ... }
我有一个 suspendCancellableCoroutine 作为动画侦听器扩展,但它在 api 30 时崩溃,这是扩展
suspend fun Animator.startAndWait() = suspendCancellableCoroutine<Unit> { continuation ->
continuation.invokeOnCancellation { cancel() }
this.addListener(object : AnimatorListenerAdapter() {
private var endedSuccessfully = true
override fun onAnimationCancel(animation: Animator?) {
endedSuccessfully = false
}
override fun onAnimationStart(animation: Animator?) {
animation?.removeListener(this)
if (continuation.isActive) {
// If the coroutine is still active...
if (endedSuccessfully) {
// ...and the Animator ended successfully, resume the coroutine
continuation.resume(Unit)
} else {
// ...and the Animator was cancelled, cancel the coroutine too
continuation.cancel()
}
}
}
})
start()
}
我是从另一个动画师的 运行 方法中调用它的
private fun createRevealAnimation() {
val x: Int = binding.root.right / 2
val y: Int = binding.root.bottom - binding.root.bottom / 9
val endRadius = hypot(binding.root.width.toDouble(), binding.root.height.toDouble()).toInt()
viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Default) {
createCircleRevealAnimator(x, y, endRadius).run {
duration = 250
withContext(Dispatchers.Main){
binding.pokeballOpen.visibility = View.VISIBLE
}
startAndWait()
navigateToListFragment()
}
}
}
private fun createCircleRevealAnimator(x: Int, y: Int, endRadius: Int): Animator {
return ViewAnimationUtils.createCircularReveal(
binding.pokeballOpen, x, y,
0f,
endRadius.toFloat()
)
}
在 api 30 之前它在每个版本上都运行良好,然后崩溃并抛出此错误
2021-02-06 17:50:42.205 29495-29590/com.sealstudios.pokemonApp.paid E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-1
Process: com.sealstudios.pokemonApp.paid, PID: 29495
kotlinx.coroutines.CompletionHandlerException: Exception in invokeOnCancellation handler for CancellableContinuation(DispatchedContinuation[Dispatchers.Default, Continuation at com.sealstudios.pokemonApp.ui.SplashScreenFragment$createRevealAnimation.invokeSuspend(SplashScreenFragment.kt:61)@472a1ed]){CancelledContinuation[kotlinx.coroutines.JobCancellationException: StandaloneCoroutine is cancelling; job=StandaloneCoroutine{Cancelling}@c735822]}@e4312b3
at kotlinx.coroutines.CancellableContinuationImpl.callCancelHandler(CancellableContinuationImpl.kt:583)
at kotlinx.coroutines.CancellableContinuationImpl.cancel(CancellableContinuationImpl.kt:195)
at kotlinx.coroutines.CancellableContinuationImpl.parentCancelled$kotlinx_coroutines_core(CancellableContinuationImpl.kt:205)
at kotlinx.coroutines.ChildContinuation.invoke(JobSupport.kt:1484)
at kotlinx.coroutines.JobSupport.notifyCancelling(JobSupport.kt:1511)
at kotlinx.coroutines.JobSupport.tryMakeCompletingSlowPath(JobSupport.kt:897)
at kotlinx.coroutines.JobSupport.tryMakeCompleting(JobSupport.kt:860)
at kotlinx.coroutines.JobSupport.makeCompletingOnce$kotlinx_coroutines_core(JobSupport.kt:825)
at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:111)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:738)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
Caused by: java.lang.IllegalStateException: The current thread must have a looper!
at android.view.Choreographer.initialValue(Choreographer.java:111)
at android.view.Choreographer.initialValue(Choreographer.java:106)
at java.lang.ThreadLocal.setInitialValue(ThreadLocal.java:180)
at java.lang.ThreadLocal.get(ThreadLocal.java:170)
at android.view.Choreographer.getInstance(Choreographer.java:288)
at android.graphics.animation.RenderNodeAnimator$DelayedAnimationHelper.<init>(RenderNodeAnimator.java:431)
at android.graphics.animation.RenderNodeAnimator.getHelper(RenderNodeAnimator.java:415)
at android.graphics.animation.RenderNodeAnimator.cancel(RenderNodeAnimator.java:226)
at com.sealstudios.pokemonApp.ui.listenerExtensions.AnimatorListenersKt$startAndWait$$inlined$suspendCancellableCoroutine$lambda.invoke(AnimatorListeners.kt:12)
at com.sealstudios.pokemonApp.ui.listenerExtensions.AnimatorListenersKt$startAndWait$$inlined$suspendCancellableCoroutine$lambda.invoke(Unknown Source:2)
at kotlinx.coroutines.InvokeOnCancel.invoke(CancellableContinuationImpl.kt:539)
at kotlinx.coroutines.CancellableContinuationImpl.callCancelHandler(CancellableContinuationImpl.kt:230)
at kotlinx.coroutines.CancellableContinuationImpl.cancel(CancellableContinuationImpl.kt:195)
at kotlinx.coroutines.CancellableContinuationImpl.parentCancelled$kotlinx_coroutines_core(CancellableContinuationImpl.kt:205)
at kotlinx.coroutines.ChildContinuation.invoke(JobSupport.kt:1484)
at kotlinx.coroutines.JobSupport.notifyCancelling(JobSupport.kt:1511)
at kotlinx.coroutines.JobSupport.tryMakeCompletingSlowPath(JobSupport.kt:897)
at kotlinx.coroutines.JobSupport.tryMakeCompleting(JobSupport.kt:860)
at kotlinx.coroutines.JobSupport.makeCompletingOnce$kotlinx_coroutines_core(JobSupport.kt:825)
at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:111)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:738)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
任何人都有任何想法我对这个很迷茫。
删除Dispatchers.Default
viewLifecycleOwner.lifecycleScope.launch { ... }