Escopos no Kotlin: Controlando Ciclo de Vida e Cancelamento de Corrotinas

Alan Gomes - Feb 27 - - Dev Community

1 – Introdução

Gerenciar o ciclo de vida de corrotinas é um dos aspectos mais importantes da programação assíncrona no Kotlin. Para isso, o Kotlin oferece escopos: estruturas que ajudam a controlar como e quando corrotinas são executadas, além de facilitar o cancelamento de tarefas quando necessário.

Neste artigo, exploraremos os principais tipos de escopos no Kotlin e suas diferenças. Você verá como escolher o escopo certo pode simplificar o gerenciamento de corrotinas no seu código.


2 – O Que São Escopos?

Escopos no Kotlin são "gestores" do ciclo de vida das corrotinas. Eles:

  1. Determinam onde e como as corrotinas serão executadas.
  2. Controlam o ciclo de vida das corrotinas, incluindo seu cancelamento.

Tipos de Escopos:

  1. Escopos baseados em classes: Utilizados para operações de longo prazo ou associadas a componentes específicos, como viewModelScope em Android.
  2. Escopos baseados em funções: Utilizados para operações temporárias e locais, como coroutineScope e supervisorScope.

3 – Escopos Baseados em Classes

3.1 – CoroutineScope

  • O que é? É a interface base para criar escopos personalizados. Você pode associar um CoroutineScope a um contexto específico (por exemplo, um Dispatcher) para gerenciar corrotinas.
  • Quando usar? Para criar escopos customizados que controlam o ciclo de vida de várias corrotinas.
  • Exemplo:
import kotlinx.coroutines.*

fun main() {
    val customScope = CoroutineScope(Dispatchers.Default)

    customScope.launch {
        println("Executando dentro do CoroutineScope: ${Thread.currentThread().name}")
    }
}
Enter fullscreen mode Exit fullscreen mode

3.2 – viewModelScope

  • O que é? Um escopo especial fornecido pela biblioteca Android Jetpack, projetado para o ciclo de vida de ViewModels. Quando o ViewModel é destruído, todas as corrotinas associadas ao viewModelScope são automaticamente canceladas.
  • Quando usar?
    Para gerenciar corrotinas associadas à UI no Android.

  • Exemplo:

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch

class MyViewModel : ViewModel() {
    fun loadData() {
        viewModelScope.launch {
            println("Carregando dados na thread: ${Thread.currentThread().name}")
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

3.3 – backgroundScope

  • O que é? Um escopo projetado para operações de longo prazo que podem continuar mesmo se o ciclo de vida do componente principal terminar.
  • Quando usar?
    Para tarefas que precisam persistir além do ciclo de vida imediato, como sincronização em segundo plano.

  • Exemplo:

import kotlinx.coroutines.*

fun main() {
    val backgroundScope = CoroutineScope(Dispatchers.IO)

    backgroundScope.launch {
        println("Executando no background: ${Thread.currentThread().name}")
    }
}
Enter fullscreen mode Exit fullscreen mode

4 – Escopos Baseados em Funções

4.1 – coroutineScope

  • O que é? Uma função suspensa que cria um escopo temporário. Todas as corrotinas dentro de um coroutineScope compartilham o mesmo Job.
  • Quando usar? Para garantir que todas as tarefas dentro de um bloco sejam concluídas ou canceladas em conjunto.
  • Exemplo:
import kotlinx.coroutines.*

suspend fun main() {
    coroutineScope {
        launch {
            println("Corrotina 1 executando...")
        }
        launch {
            println("Corrotina 2 executando...")
        }
    }
    println("Todas as corrotinas concluídas.")
}
Enter fullscreen mode Exit fullscreen mode

4.2 – supervisorScope

  • O que é? Semelhante ao coroutineScope, mas com uma diferença crucial: falhas em uma corrotina não afetam as outras dentro do escopo.
  • Quando usar? Para garantir que todas as tarefas dentro de um bloco sejam concluídas ou canceladas em conjunto.
  • Exemplo:
import kotlinx.coroutines.*

suspend fun main() {
    supervisorScope {
        launch {
            println("Corrotina 1 executando...")
            throw RuntimeException("Erro na Corrotina 1")
        }
        launch {
            println("Corrotina 2 executando...")
        }
    }
    println("SupervisorScope concluído.")
}
Enter fullscreen mode Exit fullscreen mode

5 – Comparação: coroutineScope vs. supervisorScope

Aspecto coroutineScope supervisorScope
Cancelamento Cancela todas as corrotinas em caso de falha. Apenas a corrotina com erro é cancelada.
Relacionamento entre tarefas Corrotinas dependentes umas das outras. Corrotinas independentes.
Quando usar Quando todas as tarefas precisam ter sucesso. Quando as tarefas podem falhar independentemente.

6 – Conclusão

Escopos são ferramentas poderosas no Kotlin para gerenciar o ciclo de vida de corrotinas. Eles ajudam a evitar vazamentos de recursos e facilitam o cancelamento de tarefas desnecessárias.

Resumo dos Escopos:

  1. CoroutineScope: Para escopos personalizados.
  2. viewModelScope: Para gerenciar corrotinas vinculadas a ViewModels no Android.
  3. coroutineScope: Para escopos temporários onde todas as tarefas dependem umas das outras.
  4. supervisorScope: Para tarefas independentes. No próximo artigo, exploraremos os métodos utilitários e métodos de execução que você pode usar para otimizar ainda mais suas corrotinas.

Referência
Documentação oficial do Kotlin sobre corrotinas

. . . . . . . . . . . . .