Marketplace kotlin-coroutines-expert

Expert patterns for Kotlin Coroutines and Flow, covering structured concurrency, error handling, and testing.

install
source · Clone the upstream repo
git clone https://github.com/aiskillstore/marketplace
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/aiskillstore/marketplace "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/sickn33/kotlin-coroutines-expert" ~/.claude/skills/aiskillstore-marketplace-kotlin-coroutines-expert && rm -rf "$T"
manifest: skills/sickn33/kotlin-coroutines-expert/SKILL.md
source content

Kotlin Coroutines Expert

Overview

A guide to mastering asynchronous programming with Kotlin Coroutines. Covers advanced topics like structured concurrency,

Flow
transformations, exception handling, and testing strategies.

When to Use This Skill

  • Use when implementing asynchronous operations in Kotlin.
  • Use when designing reactive data streams with
    Flow
    .
  • Use when debugging coroutine cancellations or exceptions.
  • Use when writing unit tests for suspending functions or Flows.

Step-by-Step Guide

1. Structured Concurrency

Always launch coroutines within a defined

CoroutineScope
. Use
coroutineScope
or
supervisorScope
to group concurrent tasks.

suspend fun loadDashboardData(): DashboardData = coroutineScope {
    val userDeferred = async { userRepo.getUser() }
    val settingsDeferred = async { settingsRepo.getSettings() }
    
    DashboardData(
        user = userDeferred.await(),
        settings = settingsDeferred.await()
    )
}

2. Exception Handling

Use

CoroutineExceptionHandler
for top-level scopes, but rely on
try-catch
within suspending functions for granular control.

val handler = CoroutineExceptionHandler { _, exception ->
    println("Caught $exception")
}

viewModelScope.launch(handler) {
    try {
        riskyOperation()
    } catch (e: IOException) {
        // Handle network error specifically
    }
}

3. Reactive Streams with Flow

Use

StateFlow
for state that needs to be retained, and
SharedFlow
for events.

// Cold Flow (Lazy)
val searchResults: Flow<List<Item>> = searchQuery
    .debounce(300)
    .flatMapLatest { query -> searchRepo.search(query) }
    .flowOn(Dispatchers.IO)

// Hot Flow (State)
val uiState: StateFlow<UiState> = _uiState.asStateFlow()

Examples

Example 1: Parallel Execution with Error Handling

suspend fun fetchDataWithErrorHandling() = supervisorScope {
    val task1 = async { 
        try { api.fetchA() } catch (e: Exception) { null } 
    }
    val task2 = async { api.fetchB() }
    
    // If task2 fails, task1 is NOT cancelled because of supervisorScope
    val result1 = task1.await()
    val result2 = task2.await() // May throw
}

Best Practices

  • Do: Use
    Dispatchers.IO
    for blocking I/O operations.
  • Do: Cancel scopes when they are no longer needed (e.g.,
    ViewModel.onCleared
    ).
  • Do: Use
    TestScope
    and
    runTest
    for unit testing coroutines.
  • Don't: Use
    GlobalScope
    . It breaks structured concurrency and can lead to leaks.
  • Don't: Catch
    CancellationException
    unless you rethrow it.

Troubleshooting

Problem: Coroutine test hangs or fails unpredictably. Solution: Ensure you are using

runTest
and injecting
TestDispatcher
into your classes so you can control virtual time.