kotlin-concurrency-and-flow

Reviews Kotlin coroutine scope ownership, cancellation, and Flow state versus event modeling.

1.0k|46|Updated May 12, 2026
One-click install
npx skills add https://github.com/chrisbanes/skills --skill kotlin-concurrency-and-flow
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: kotlin-concurrency-and-flow
Source: https://github.com/chrisbanes/skills/tree/main/skills/kotlin-concurrency-and-flow
Command: npx skills add https://github.com/chrisbanes/skills --skill kotlin-concurrency-and-flow

SYSTEM DOCUMENTATION & REQUIREMENTS

💡 This Skill includes references (resource) components.

What problem does it solve?

Kotlin codebases often hide unstructured launches, stored CoroutineScopes, runBlocking calls, and misused SharedFlow or Channel primitives, making it impossible to tell who owns cancellation, replay, and failure behavior. This Skill provides a structured review procedure for assigning every piece of asynchronous work an explicit owner and lifetime.

Core Features & Use Cases

  • Structured concurrency review: Detects stored or injected CoroutineScopes, raw Thread/Executor work, init-block launches, broad catches that swallow CancellationException, and misplaced runBlocking boundaries, then guides conversion to suspending APIs.
  • Flow state and event modeling: Guides selection between StateFlow, SharedFlow, Channel, and cold Flow based on replay, fan-out, buffering, and synchronous .value requirements, including stateIn and SharingStarted configuration.
  • Use Case: While reviewing a ViewModel that exposes navigation via a replay-zero SharedFlow, the Skill identifies event loss during collector gaps and recommends a buffered Channel exposed with receiveAsFlow() instead.

Quick Start

Review this Kotlin repository class for hidden coroutine scope ownership and check whether its SharedFlow events should be a Channel or StateFlow.

Frequently Asked Questions about kotlin-concurrency-and-flow

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I choose between StateFlow, SharedFlow, and Channel in Kotlin?

Choose StateFlow for current renderable state with synchronous .value access, SharedFlow for hot broadcast without .value, and a buffered Channel exposed via receiveAsFlow() for exactly-once handoff to one consumer. Base the choice on replay, fan-out, and absent-collector behavior.

How do I fix a stored CoroutineScope in a repository class?

Replace the stored scope with suspending APIs and let the caller's lifecycle owner launch the work. A cancelled stored scope can make future launches silently do nothing, so expose suspend functions and follow compiler-reported callers upward.

When is it acceptable to use runBlocking in Kotlin?

runBlocking is acceptable only at true blocking boundaries such as CLI main functions, synchronous Java or framework bridges like ContentProvider methods, and migration shims. Keep the body to the direct suspending call and use runTest in tests.

Why does my SharedFlow lose events when no collector is active?

A replay-zero SharedFlow drops events emitted while no collector is subscribed. For one-shot events that must survive a collector gap, use a buffered Channel exposed as receiveAsFlow(), which queues each event until one consumer receives it.

Should ViewModels expose suspend functions or launch internally?

A UI state holder may launch on its lifecycle scope, such as viewModelScope, when handling an actual UI event. Its lower layers like repositories and use cases should remain suspending so the caller controls cancellation and error handling.