Sobes.tech
Middle+

¿Qué problemas inesperados pueden surgir al trabajar con corrutinas en Android?

sobes.tech AI

Respuesta de la IA

  • Cancelación inesperada: La coroutine puede ser cancelada implícitamente, por ejemplo, al cambiar la configuración del dispositivo o cerrar una Activity/Fragment, si el contexto del ciclo de vida no se gestiona cuidadosamente. Esto puede llevar a fugas de memoria o operaciones no completadas.
  • Problemas con el contexto (propagación del contexto): La transferencia del contexto de coroutine entre capas de la aplicación (UI, ViewModel, Repository) requiere atención. Un uso incorrecto del contexto puede causar bloqueos en la UI o bloqueo de hilos.
  • Fugas de recursos por excepciones no manejadas: Las excepciones no controladas en coroutines hijas pueden cancelar implícitamente al padre, pero los recursos asignados dentro de la hija pueden no liberarse.
  • Flujos "fríos" (Flow) y su gestión del ciclo de vida: Flow es perezoso por naturaleza y requiere recolección activa de datos. Si la recolección no se gestiona correctamente (por ejemplo, con flowWithLifecycle o collectLatest), puede producir comportamientos no deseados al cambiar el estado de la UI o el ciclo de vida.
  • Llamadas bloqueantes: Incluir llamadas bloqueantes (como operaciones de red o archivos) en una coroutine que se ejecuta en el dispatcher principal (Dispatchers.Main) provocará un ANR.
// Ejemplo de posible problema con cancelación de coroutine al cambiar la configuración
class MyViewModel : ViewModel() {
    fun loadData() {
        viewModelScope.launch {
            // Operación prolongada
            delay(5000)
            // Si la Activity se recrea durante el delay, esta línea puede no ejecutarse
            println("Datos cargados")
        }
    }
}

// Ejemplo de llamada bloqueante en el dispatcher principal
import kotlinx.coroutines.*

fun performBlockingOperation() {
    runBlocking { // ¡No usar en el hilo de UI!
        delay(1000) // Bloquea el hilo
    }
}

// Debería ser así:
fun performNonBlockingOperation() {
    CoroutineScope(Dispatchers.Default).launch {
        delay(1000) // No bloquea el hilo principal
    }
}