Entradas

Tratamiento de excepciones en las corrutinas

TL; DR Cuando se lanza una excepción dentro de una corrutina: Debemos capturarla con un try-catch , igual que cuando se lanza en cualquier otro lado. De no capturarla, la corrutina se cancela y la excepción se propaga hasta la corrutina raíz (la primera, lanzada con el CoroutineScope original), para ser capturada por su CoroutineExceptionHandler . Si la corrutina raíz tiene CoroutineExceptionHandler , la excepción es capturada ahí y la aplicación no peta. try-catch Mira este código y olvídalo inmediatamente: try { viewModelScope . launch { val numero = "Texto" .toInt() println(numero.toString()) } } catch (t: Throwable) { // Aquí nunca se capturará nada. } Envolver el lanzamiento de la corrutina en un bloque try-catch NO SIRVE DE NADA porque el código que lanza la excepción no va a suceder en ese momento. El código de la corrutina se ejecutará de manera asíncrona, es decir, que aunque esté ahí escrito, no se va a ejecut...

¿Qué es realmente un contexto de corrutinas?

Entrada en construcción.

Cancelación de corrutinas

Entrada en construcción.

Gestión de la ejecución de las corrutinas

TL; DR Lo que se ejecuta en una corrutina se ejecuta en un hilo. Android decide si lo pone todo en un hilo, o en varios, o si crea o reutiliza hilos. Las corrutinas son concurrentes entre sí porque son hilos y los hilos son concurrentes entre sí. Cuando dos hilos se ejecutan a la par, si imprimimos logs desde cada uno de ellos, estos saldrán desordenados porque no se pueden imprimir solapados ( duh! ). "¿Cuán concurrentes son las corrutinas?" o "¿por qué sale desordenado el código?" son las preguntas que te han traído aquí. Asíncrono y concurrente son cosas distintas (podéis leer esto mejor en este artículo de Víctor Gómez de Juan ). Asincronía: el código en un hilo es síncrono, es decir, una línea se ejecuta después de la otra, pero con las corrutinas (al igual que con los callbacks ) el código de la corrutina no se ejecuta inmediatamente después de lanzarla. Lanzar una corrutina no significa ejecutarla inmediatamente, significa que le decim...

async()

El constructor de corrutinas async() sirve para lanzar corrutinas de las cuales necesitamos el resultado , pero permitiéndonos indicar cuándo queremos recuperarlo (es decir, sin suspender la corrutina actual hasta que sea necesario). async() FUNCIONA EXACTAMENTE IGUAL QUE launch() : Android lo ejecuta asíncronamente cuando él lo disponga y su ejecución es concurrente a lo que suceda en otros hilos ( Gestión de la ejecución de las corrutinas ). La peculiaridad que tiene es que nos permite solicitar el resultado de la corrutina mediante su job . Al igual que launch() , async() devuelve un Job , pero este es de tipo Deferred<T> . Deferred<T> tiene como particularidad la función de suspensión await() , que suspende la corrutina en la que ha sido llamado hasta que finaliza la ejecución de async() y obtenemos su resultado ( <T> ). Esto quiere decir que, para cuando llamemos a await() , si el resultado aún no ha sido calculado, la corrutina en la que se hace la llam...

Funciones de suspensión

Funciones de suspensión ¿Cuándo voy a querer crear funciones de extensión? Funciones de suspensión constructoras de ámbito withContext() coroutineScope() y supervisorScope() delay() Suspensión y concurrencia son conceptos opuestos() ¿Qué es realmente suspender? Garantizar la seguridad del hilo principal ¿Cuándo sí y cuándo no tendría que garantizar la seguridad del hilo principal? ¿Es async() intercambiable con withContext()? TL; DR Suspender significa detener la ejecución del código de una corrutina en una línea hasta que termina una operación asíncrona y la reanuda cuando termine. Detener la ejecución del código de una corrutina en ningún caso significa detener el hilo. Esto se hace a nuestras espaldas mediante un callback llamado Continuation . La continuation encapsula todo el código que se ha escrito después de la función de suspensión y se le pasa a esta para ser llamado cuando termine. Una...

¿Cómo usar las corrutinas en una aplicación?

¿Cómo voy a usar las corrutinas en mi aplicación? TL; DR Evita a toda costa usar GlobalScope , no te compliques la vida creando scopes tú mismo y hazte un favor y ejecútalo todo con viewModelScope . launch () . Si tienes que volver al hilo principal, usa un LiveData . En Android tendrás casi el 100% de las veces uno de estos dos escenarios: Solo petición: quieres ejecutar un código y no hay nada que hacer después, no importa si falla, si no falla... Quiero lanzarlo y olvidarme. Petición y respuesta: quieres solicitar datos y pintarlos cuando lleguen, o ejecutar algo y hacer un cambio en la UI cuando termine. Para ninguno de estos casos te interesa usar lifecycleScope , ya que tus peticiones no deberían verse afectadas por los cambios de configuración de la activity . Si declaras las peticiones en el onCreate() , se estarían destruyendo y lanzando una y otra vez cada vez que girases la pantalla. Así que no quieres usar ese ámbito. Este problema lo solucio...