Tuve un bloqueo debido a Kotlin JobCancellationException.
El siguiente es el detalle sobre el accidente:
kotlinx.coroutines.JobCancellationException: Job was cancelled; job=SupervisorJobImpl{Cancelling}@131dbe3Todo lo que sé es que SupervisorJobImpl es para ViewModelScope, y se llamará método de cancelación cuando finalice el ciclo de vida de ViewModel.
Estaba tan confundido acerca de la excepción porque las corrutinas de Kotlin simplemente ignorarán la excepción, pero se lanzó y provocó el bloqueo de la aplicación. Si tiene pila, puedo averiguarlo, pero no es así, solo dime que el trabajo fue cancelado.
Pasé más de 3 días en la excepción, pero no tengo idea.
Vi el video: KotlinConf 2019: Coroutines! ¡Hazte con todos! por Florina Muntenescu y Manuel Vivo , descubrí que si el alcance está cancelado, y si llama a esperar en un Diferido, arrojará la Excepción, pero no encontré espera en el alcance cancelado.
Entonces, ¿alguien puede mostrarme un código que quizás cause la misma excepción y haga que la aplicación se bloquee? Gracias, allí.
Finalmente, encontré lo que causa la Excepción y la dirección del problema fluye:
kotlin.coroutines.channels.awaitClose: JobCancellationException
En realidad, awaitClose no lanzará JobCancellationException , porque awaitClose es una función suspendida cancelable. El método de offer lanzará JobCancellationException si el trabajo se canceló porque la offer no es una función suspendida cancelable.
Por cierto, callbackFlow es una API experimental, por lo que puede causar algún error, por lo que cuando la usamos, debemos tener cuidado. Porque no siempre ignorará JobCancellationException cuando se canceló el trabajo, y no creo que sea amigable para los desarrolladores.
Ahora he encontrado 2 situaciones que causarán JobCancellationException , por lo que debemos try catch la excepción.
async await , cuando llamamos al método await necesitamos try catch . Y puedes encontrar un ejemplo en el Video .
callbackFlow offer , cuando llamamos al método de offer , debemos try catch . Y puede encontrar un ejemplo en el problema anterior.
Acabo de ver el mismo problema. El problema se debió a que la actividad se terminó manualmente antes de que el trabajo lograra completarse.
class MyApp: Application() { override fun onCreate() { super.onCreate() System.setProperty(DEBUG_PROPERTY_NAME, DEBUG_PROPERTY_VALUE_ON) }de esta manera podrá identificar la causa principal del problema y tratarlo
Sé que llego tarde, pero puede verificar el estado del trabajo antes de ofrecer objetos. Me gusta esto
if(isActive) offer(Resource.success(response))isActive es Coroutine Scope
Tengo el mismo error que tu. Entonces trato de escribir extensiones de flujo simples como a continuación:
fun <P> Flow<DataResult<P>>.safeStart(start: suspend FlowCollector<DataResult<P>>.() -> Unit) : Flow<DataResult<P>> = onStart { if (!currentCoroutineContext().isActive) return@onStart start() } fun <P> Flow<DataResult<P>>.safeCatch(onCatch: suspend FlowCollector<DataResult<P>>.(cause: Throwable) -> Unit) : Flow<DataResult<P>> = catch { if (!currentCoroutineContext().isActive) return@catch onCatch(it) } suspend inline fun <P> Flow<DataResult<P>>.safeCollect(crossinline onCollect: suspend (value: DataResult<P>) -> Unit) : Unit = collect { if (!currentCoroutineContext().isActive) return@collect onCollect(it) }Cerré un ViewModel y un cuadro de diálogo y luego comencé un Job . Condujo a esta excepción y a la cancelación de la solicitud HTTP: HTTP FAILED: java.io.IOException: Canceled .
close() modelScope.launch { val response = withContext(Dispatchers.IO) { ... } response?.let { ... } } Simplemente moví close() hasta el final.
Tuve el mismo bloqueo cuando usé callbackFlow con offer con coroutines versión 1.3.5 . Ahora, en lugar de ofrecer, uso trySend y está arreglado.
Nota: el método trySend está disponible (y la offer está en desuso) cuando actualiza la versión de rutinas a:
org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.0