Como configurar e usar corutinas em projetos Kotlin?
sobes.tech IA
Resposta da IA
Para configurar as corrotinas, é necessário adicionar a dependência correspondente no arquivo build.gradle.
// build.gradle (módulo app)
dependencies {
//... outras dependências
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") // Para JVM, Android, JS, Native
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3") // Para Android (se necessário Dispatchers.Main)
}
O uso de corrotinas inclui:
-
Escopo (Scope): Definir o escopo no qual as corrotinas serão executadas e gerenciar seu ciclo de vida.
GlobalScope: Escopo de toda a aplicação, usar com cuidado, pois pode causar vazamentos de memória.CoroutineScope: Criado explicitamente, permite controlar o cancelamento das corrotinas.- Escopos predefinidos em frameworks (por exemplo,
lifecycleScopeem Android ViewModel).
// Exemplo com CoroutineScope val myScope = CoroutineScope(Dispatchers.Default + SupervisorJob()) // Criar escopo com Dispatcher e Job fun performBackgroundTask() { myScope.launch { // Iniciar uma corrotina // Processo de cálculo longo } } fun cancelAllTasks() { myScope.cancel() // Cancelar todas as corrotinas no escopo } -
Construtores de corrotinas (Builders): Funções para lançar corrotinas.
launch: Inicia uma corrotina que não retorna resultado explícito (retorna umJob).async: Inicia uma corrotina que retorna resultado na forma deDeferred.
import kotlinx.coroutines.* suspend fun fetchData() = coroutineScope { // coroutineScope - construtor para concorrência estruturada val data1 = async { networkCall1() } // async retorna um Deferred val data2 = async { networkCall2() } // ... processamento de dados após recebê-los data1.await() // Obter resultado de Deferred, suspende a corrotina até que seja concluído data2.await() } suspend fun networkCall1(): String { delay(1000) // Simulação de requisição de rede return "Data 1" } suspend fun networkCall2(): String { delay(1500) return "Data 2" } fun startFetching() = runBlocking { // runBlocking - construtor para bloquear a thread atual (para main ou testes) launch { // launch retorna um Job println("Fetching data...") fetchData() println("Data fetched!") } } -
Despachantes (Dispatchers): Determinam em qual thread ou pool de threads a corrotina será executada.
Dispatchers.Default: Para tarefas intensivas em CPU.Dispatchers.IO: Para operações de E/S bloqueantes (arquivos, rede).Dispatchers.Main: Thread principal (apenas para Android e Swing/JavaFX).Dispatchers.Unconfined: Executa a corrotina na thread que a chamou, ela se suspende e depois é retomada na thread que a retomou.
import kotlinx.coroutines.* fun simpleTask() { GlobalScope.launch(Dispatchers.IO) { // Especificar o despachante // Executar operação de E/S println("Executando na thread: ${Thread.currentThread().name}") } } fun main() = runBlocking { launch(Dispatchers.Default) { println("Thread padrão: ${Thread.currentThread().name}") } launch(Dispatchers.Unconfined) { println("Thread não confinado 1: ${Thread.currentThread().name}") delay(100) // Suspensão println("Thread não confinado 2: ${Thread.currentThread().name}") // Recomeço em outro thread (possivelmente) } delay(200) // Esperar a conclusão das corrotinas } -
Funções de suspensão (Suspending functions): Funções marcadas com a palavra-chave
suspend, que podem ser suspensas e retomadas sem bloquear o thread. Só podem ser chamadas de outras funções de suspensão ou blocos de corrotinas. -
Tratamento de cancelamento e exceções: As corrotinas suportam cancelamento estruturado e propagação de exceções.
- Cancelamento:
import kotlinx.coroutines.* fun cancellableTask() = GlobalScope.launch { try { repeat(1000) { i -> println("Trabalhando $i ...") delay(100) // função de suspensão que respeita o cancelamento } } catch (e: CancellationException) { println("Tarefa foi cancelada!") } finally { println("Limpando...") } } fun main() = runBlocking { val job = cancellableTask() delay(500) // Esperar um pouco job.cancelAndJoin() // Cancelar e aguardar a finalização } - Exceções: No caso de
launch, uma exceção não capturada levará à queda do aplicativo (no Android, por padrão). No caso deasync, a exceção será lançada ao chamarawait(). Para controle mais granular, usam-seCoroutineExceptionHandlerouSupervisorJob.
import kotlinx.coroutines.* fun main() = runBlocking { val handler = CoroutineExceptionHandler { _, exception -> println("Exceção capturada: $exception") } val job = GlobalScope.launch(handler) { // Aplicar o manipulador throw IllegalStateException("Algo deu errado") } job.join() // Aguardar a finalização } - Cancelamento: