Kotlin Concurrency Expert
Overview
Review and fix Kotlin Coroutines issues in Android codebases by applying structured concurrency, lifecycle safety, proper scoping, and modern best practices with minimal behavior changes.
Workflow
1. Triage the Issue
- Capture the exact error, crash, or symptom (ANR, memory leak, race condition, incorrect state).
- Check project coroutines setup:
kotlinx-coroutines-androidversion,lifecycle-runtime-ktxversion. - Identify the current scope context (
viewModelScope,lifecycleScope, custom scope, or none). - Confirm whether the code is UI-bound (
Dispatchers.Main) or intended to run off the main thread (Dispatchers.IO,Dispatchers.Default). - Verify Dispatcher injection patterns for testability.
2. Apply the Smallest Safe Fix
Prefer edits that preserve existing behavior while satisfying structured concurrency and lifecycle safety.
Common fixes:
- ANR / Main thread blocking: Move heavy work to
withContext(Dispatchers.IO)orDispatchers.Default; ensure suspend functions are main-safe. - Memory leaks / zombie coroutines: Replace
GlobalScopewith a lifecycle-bound scope (viewModelScope,lifecycleScope, or injectedapplicationScope). - Lifecycle collection issues: Replace deprecated
launchWhenStartedwithrepeatOnLifecycle(Lifecycle.State.STARTED). - State exposure: Encapsulate
MutableStateFlow/MutableSharedFlow; expose read-onlyStateFloworFlow. - CancellationException swallowing: Ensure generic
catch (e: Exception)blocks rethrowCancellationException. - Non-cooperative cancellation: Add
ensureActive()oryield()in tight loops for cooperative cancellation. - Callback APIs: Convert listeners to
callbackFlowwith properawaitClosecleanup. - Hardcoded Dispatchers: Inject
CoroutineDispatchervia constructor for testability.


