Sobes.tech
Middle+

¿Cómo sincronizar las corrutinas en Android?

sobes.tech AI

Respuesta de la IA

Para sincronizar corutinas en Android, se pueden usar varios enfoques, dependiendo de la tarea específica:

  • Join: Esperar a que otra corutina termine.

    // Iniciar la primera corutina
    val job1 = CoroutineScope(Dispatchers.Default).launch {
        delay(1000)
        println("Trabajo 1 terminado")
    }
    
    // Iniciar la segunda corutina
    val job2 = CoroutineScope(Dispatchers.Default).launch {
        delay(500)
        println("Trabajo 2 terminado")
    }
    
    // Esperar a que ambas corutinas terminen
    job1.join()
    job2.join()
    
    println("Todos los trabajos terminados")
    
  • Await: Esperar el resultado de una operación asíncrona representada por Deferred.

    // Operación asíncrona que devuelve un resultado
    val deferredResult = CoroutineScope(Dispatchers.Default).async {
        delay(1000)
        "Resultado de async"
    }
    
    // Esperar el resultado
    val result = deferredResult.await()
    println(result)
    
  • CoroutineScope.coroutineScope: Crear un nuevo ámbito de alcance que solo terminará después de que todas las corutinas hijas hayan finalizado. Útil para competencia estructurada.

    suspend fun doParallelWork() {
        coroutineScope { // Crear un nuevo scope de competencia estructurada
            launch { delay(1000); println("Tarea 1 terminada") }
            launch { delay(500); println("Tarea 2 terminada") }
        } // Este punto solo se alcanzará después de que las tareas 1 y 2 hayan finalizado
        println("Todas las tareas paralelas terminadas")
    }
    
  • Semántica de actores (Channel): Para intercambio de mensajes y sincronización de acceso a datos modificables entre corutinas.

    // Crear un canal para intercambiar Int
    val channel = Channel<Int>()
    
    CoroutineScope(Dispatchers.Default).launch {
        // Enviar datos al canal
        for (i in 1..5) {
            channel.send(i)
        }
        channel.close() // Cerrar el canal después de enviar
    }
    
    CoroutineScope(Dispatchers.Default).launch {
        // Recibir datos del canal
        for (value in channel) {
            println("Recibido $value")
        }
    }
    
  • Mutex: Para garantizar acceso exclusivo a un recurso compartido.

    import kotlinx.coroutines.sync.Mutex
    import kotlinx.coroutines.sync.withLock
    
    val mutex = Mutex()
    var counter = 0
    
    suspend fun incrementCounter() {
        mutex.withLock { // Adquirir el mutex
            counter++
            // El mutex se liberará automáticamente al salir del bloque
        }
    }
    

La elección del método depende de qué exactamente se necesita sincronizar: esperar a que termine, obtener un resultado, gestionar tareas paralelas, intercambiar datos o acceso exclusivo. coroutineScope es el enfoque recomendado por defecto para competencia estructurada.