Sobes.tech
Middle+

Como sincronizar corrotinas no Android?

sobes.tech IA

Resposta da IA

Para sincronizar corutinas no Android, pode usar várias abordagens, dependendo da tarefa específica:

  • Join: Aguardar a conclusão de outra corutina.

    // Iniciar a primeira corutina
    val job1 = CoroutineScope(Dispatchers.Default).launch {
        delay(1000)
        println("Job 1 terminado")
    }
    
    // Iniciar a segunda corutina
    val job2 = CoroutineScope(Dispatchers.Default).launch {
        delay(500)
        println("Job 2 terminado")
    }
    
    // Aguardar a conclusão de ambas as corutinas
    job1.join()
    job2.join()
    
    println("Todos os jobs terminados")
    
  • Await: Aguardar o resultado de uma operação assíncrona representada por Deferred.

    // Operação assíncrona que retorna um resultado
    val deferredResult = CoroutineScope(Dispatchers.Default).async {
        delay(1000)
        "Resultado do async"
    }
    
    // Aguardar o resultado
    val result = deferredResult.await()
    println(result)
    
  • CoroutineScope.coroutineScope: Criar um novo escopo de alcance que só terminará após a conclusão de todas as corutinas filhas. Útil para concorrência estruturada.

    suspend fun doParallelWork() {
        coroutineScope { // Criar um novo escopo de concorrência estruturada
            launch { delay(1000); println("Tarefa 1 concluída") }
            launch { delay(500); println("Tarefa 2 concluída") }
        } // Este ponto só será atingido após a conclusão de tarefa 1 e tarefa 2
        println("Todas as tarefas paralelas concluídas")
    }
    
  • Semântica de atores (Channel): Para troca de mensagens e sincronização de acesso a dados modificáveis entre corutinas.

    // Criar um canal para troca de Int
    val channel = Channel<Int>()
    
    CoroutineScope(Dispatchers.Default).launch {
        // Enviar dados pelo canal
        for (i in 1..5) {
            channel.send(i)
        }
        channel.close() // Fechar o canal após o envio
    }
    
    CoroutineScope(Dispatchers.Default).launch {
        // Receber dados do canal
        for (value in channel) {
            println("Recebido $value")
        }
    }
    
  • Mutex: Para garantir acesso exclusivo a um recurso comum.

    import kotlinx.coroutines.sync.Mutex
    import kotlinx.coroutines.sync.withLock
    
    val mutex = Mutex()
    var counter = 0
    
    suspend fun incrementCounter() {
        mutex.withLock { // Adquirir o mutex
            counter++
            // O mutex será liberado automaticamente ao sair do bloco
        }
    }
    

A escolha do método depende do que exatamente precisa ser sincronizado: aguardar a conclusão, obter resultado, gerenciar tarefas paralelas, trocar dados ou acesso exclusivo. coroutineScope é a abordagem recomendada por padrão para concorrência estruturada.