Pular para o conteúdo
Skillpedia
Código em geral280 mil · #68

kotlin-coroutines-flows

Faz seu agente usar Coroutines e Flow em Kotlin para Android e KMP. Ajuda a gerenciar tarefas assíncronas de forma estruturada e a lidar com erros.

O que ela faz

Ajuda a escrever e depurar código que roda em segundo plano (assíncrono) em aplicativos Android e multiplataforma. Facilita o gerenciamento de tarefas que precisam acontecer ao mesmo tempo ou em resposta a eventos.

Quando usar

  • ✓Quando você precisa que seu aplicativo faça várias coisas ao mesmo tempo.
  • ✓Ao exibir dados que mudam com o tempo na tela.
  • ✓Para lidar com erros em operações que rodam em segundo plano.

Exemplo do que pedir para a IA

“Como faço para que meu aplicativo baixe uma imagem enquanto o usuário navega por outra tela sem travar?”

Quer saber mais? Abra as seções abaixo.

Como usar

O jeito mais fácil: copie a mensagem abaixo e cole no Claude, ChatGPT, Cursor ou outra IA. Ela lê a skill e segue as instruções.

Link da skill

https://github.com/affaan-m/ECC/blob/main/pi/core/skills/kotlin-coroutines-flows/SKILL.md

Mensagem pronta para colar

Use esta skill para me ajudar: https://github.com/affaan-m/ECC/blob/main/pi/core/skills/kotlin-coroutines-flows/SKILL.md Leia o arquivo SKILL.md desse link e siga as instruções dele na minha tarefa.
Como funciona

Ele usa 'corrotinas' para executar tarefas em segundo plano de forma organizada e 'Flows' para lidar com fluxos de dados que mudam. Isso permite que o código seja mais limpo e fácil de entender.

Instalação

Jeito mais fácil: copie o link da skill e cole no Claude, ChatGPT ou Cursor pedindo para seguir as instruções.

No terminal (Claude Code, Codex, Cursor), na pasta do projeto:

npx skills add affaan-m/ECC --skill kotlin-coroutines-flows

Ou baixe só o arquivo:

curl -L https://raw.githubusercontent.com/affaan-m/ECC/main/pi/core/skills/kotlin-coroutines-flows/SKILL.md -o SKILL.md
Conteúdo técnico (SKILL.md)

Tradução do texto original do autor no GitHub. Os comandos e códigos estão como no original.

Kotlin Coroutines & Flows

Padrões para concorrência estruturada, streams reativos baseados em Flow e testes de corrotinas em projetos Android e Kotlin Multiplatform.

Quando Ativar

  • Escrevendo código assíncrono com corrotinas Kotlin
  • Usando Flow, StateFlow ou SharedFlow para dados reativos
  • Lidando com operações concorrentes (carregamento paralelo, debounce, retry)
  • Testando coroutines e Flows
  • Gerenciando escopos de corrotinas e cancelamento

Concorrência Estruturada

Hierarquia de Escopos

Application
  └── viewModelScope (ViewModel)
        └── coroutineScope { } (structured child)
              ├── async { } (concurrent task)
              └── async { } (concurrent task)

Sempre use concorrência estruturada — nunca GlobalScope:

// BAD
GlobalScope.launch { fetchData() }

// GOOD — scoped to ViewModel lifecycle
viewModelScope.launch { fetchData() }

// GOOD — scoped to composable lifecycle
LaunchedEffect(key) { fetchData() }

Decomposição Paralela

Use coroutineScope + async para trabalho paralelo:

suspend fun loadDashboard(): Dashboard = coroutineScope {
    val items = async { itemRepository.getRecent() }
    val stats = async { statsRepository.getToday() }
    val profile = async { userRepository.getCurrent() }
    Dashboard(
        items = items.await(),
        stats = stats.await(),
        profile = profile.await()
    )
}

SupervisorScope

Use supervisorScope quando falhas de filhos não devem cancelar irmãos:

suspend fun syncAll() = supervisorScope {
    launch { syncItems() }       // failure here won't cancel syncStats
    launch { syncStats() }
    launch { syncSettings() }
}

Padrões de Flow

Cold Flow — Conversão de Um-Disparo para Stream

fun observeItems(): Flow<List<Item>> = flow {
    // Re-emits whenever the database changes
    itemDao.observeAll()
        .map { entities -> entities.map { it.toDomain() } }
        .collect { emit(it) }
}

StateFlow para Estado da UI

class DashboardViewModel(
    observeProgress: ObserveUserProgressUseCase
) : ViewModel() {
    val progress: StateFlow<UserProgress> = observeProgress()
        .stateIn(
            scope = viewModelScope,
            started = SharingStarted.WhileSubscribed(5_000),
            initialValue = UserProgress.EMPTY
        )
}

WhileSubscribed(5_000) mantém o upstream ativo por 5 segundos após o último assinante sair — sobrevive a mudanças de configuração sem reiniciar.

Combinando Múltiplos Flows

val uiState: StateFlow<HomeState> = combine(
    itemRepository.observeItems(),
    settingsRepository.observeTheme(),
    userRepository.observeProfile()
) { items, theme, profile ->
    HomeState(items = items, theme = theme, profile = profile)
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), HomeState())

Operadores de Flow

// Debounce search input
searchQuery
    .debounce(300)
    .distinctUntilChanged()
    .flatMapLatest { query -> repository.search(query) }
    .catch { emit(emptyList()) }
    .collect { results -> _state.update { it.copy(results = results) } }

// Retry with exponential backoff
fun fetchWithRetry(): Flow<Data> = flow { emit(api.fetch()) }
    .retryWhen { cause, attempt ->
        if (cause is IOException && attempt < 3) {
            delay(1000L * (1 shl attempt.toInt()))
            true
        } else {
            false
        }
    }

SharedFlow para Eventos Únicos

class ItemListViewModel : ViewModel() {
    private val _effects = MutableSharedFlow<Effect>()
    val effects: SharedFlow<Effect> = _effects.asSharedFlow()

    sealed interface Effect {
        data class ShowSnackbar(val message: String) : Effect
        data class NavigateTo(val route: String) : Effect
    }

    private fun deleteItem(id: String) {
        viewModelScope.launch {
            repository.delete(id)
            _effects.emit(Effect.ShowSnackbar("Item deleted"))
        }
    }
}

// Collect in Composable
LaunchedEffect(Unit) {
    viewModel.effects.collect { effect ->
        when (effect) {
            is Effect.ShowSnackbar -> snackbarHostState.showSnackbar(effect.message)
            is Effect.NavigateTo -> navController.navigate(effect.route)
        }
    }
}

Dispatchers

// Trabalho intensivo de CPU
withContext(Dispatchers.Default) { parseJson(largePayload) }

// Trabalho limitado por IO
withContext(Dispatchers.IO) { database.query() }

// Thread principal (UI) — padrão em viewModelScope

…
Perguntas frequentes

O que são corrotinas?

São como pequenas tarefas que podem ser executadas em segundo plano sem interromper o funcionamento principal do aplicativo.

O que é um Flow?

É uma forma de lidar com dados que chegam em sequência, como atualizações de uma lista ou eventos do usuário.

Por que não usar `GlobalScope`?

`GlobalScope` cria tarefas que vivem para sempre, o que pode causar vazamentos de memória. Usar escopos definidos (como `viewModelScope`) garante que as tarefas sejam canceladas quando não forem mais necessárias.

Detalhes

Descrição original do autor

Kotlin Coroutines and Flow patterns for Android and KMP — structured concurrency, Flow operators, StateFlow, error handling, and testing. Use when writing coroutines or Flow code on Android or KMP, or debugging cancellation and concurrency.

repo: affaan-m/ECC

Popularidade

Estrelas no GitHub
280 mil
Posição no ranking
#68
Licença
MIT
Atualizada em
15/10/2026

Essa skill é útil?

0

Entre para votar.

Comentários

  • …

Mais skills deste repositório

Skills parecidas