Authoritative rules and patterns for production-quality Kotlin Coroutines onto Android. Covers structured concurrency, lifecycle integration, and reactive streams.
Scanned 9/12/2026
Install to Claude Code
npx -y skills add thedixitjain/the-mega-skill-library --skill android-coroutines --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Android Coroutines?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/thedixitjain-android-coroutines)More formats (shields.io, HTML) on the badges page.
---
name: android-coroutines
description: "Authoritative rules and patterns for production-quality Kotlin Coroutines onto Android. Covers structured concurrency, lifecycle integration, and reactive streams."
category: mobile-and-platform
source_repo: new-silvermoon/awesome-android-agent-skills
source_path: ".github/skills/concurrency_and_networking/android-coroutines/SKILL.md"
source_url: https://github.com/new-silvermoon/awesome-android-agent-skills/blob/HEAD/.github/skills/concurrency_and_networking/android-coroutines/SKILL.md
---
# Android Coroutines Expert Skill
This skill provides authoritative rules and patterns for writing production-quality Kotlin Coroutines code on Android. It enforces structured concurrency, lifecycle safety, and modern best practices (2025 standards).
## Responsibilities
* **Asynchronous Logic**: Implementing suspend functions, Dispatcher management, and parallel execution.
* **Reactive Streams**: Implementing `Flow`, `StateFlow`, `SharedFlow`, and `callbackFlow`.
* **Lifecycle Integration**: Managing scopes (`viewModelScope`, `lifecycleScope`) and safe collection (`repeatOnLifecycle`).
* **Error Handling**: Implementing `CoroutineExceptionHandler`, `SupervisorJob`, and proper `try-catch` hierarchies.
* **Cancellability**: Ensuring long-running operations are cooperative using `ensureActive()`.
* **Testing**: Setting up `TestDispatcher` and `runTest`.
## Applicability
Activate this skill when the user asks to:
* "Fetch data from an API/Database."
* "Perform background processing."
* "Fix a memory leak" related to threads/tasks.
* "Convert a listener/callback to Coroutines."
* "Implement a ViewModel."
* "Handle UI state updates."
## Critical Rules & Constraints
### 1. Dispatcher Injection (Testability)
* **NEVER** hardcode Dispatchers (e.g., `Dispatchers.IO`, `Dispatchers.Default`) inside classes.
* **ALWAYS** inject a `CoroutineDispatcher` via the constructor.
* **DEFAULT** to `Dispatchers.IO` in the constructor argument for convenience, but allow it to be overridden.
```kotlin
// CORRECT
class UserRepository(
private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
) { ... }
// INCORRECT
class UserRepository {
fun getData() = withContext(Dispatchers.IO) { ... }
}
```
### 2. Main-Safety
* All suspend functions defined in the Data or Domain layer must be **main-safe**.
* **One-shot calls** should be exposed as `suspend` functions.
* **Data changes** should be exposed as `Flow`.
* The caller (ViewModel) should be able to call them from `Dispatchers.Main` without blocking the UI.
* Use `withContext(dispatcher)` inside the repository implementation to move execution to the background.
### 3. Lifecycle-Aware Collection
* **NEVER** collect a flow directly in `lifecycleScope.launch` or `launchWhenStarted` (deprecated/unsafe).
* **ALWAYS** use `repeatOnLifecycle(Lifecycle.State.STARTED)` for collecting flows in Activities or Fragments.
```kotlin
// CORRECT
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.uiState.collect { ... }
}
}
```
### 4. ViewModel Scope Usage
* Use `viewModelScope` for initiating coroutines in ViewModels.
* Do not expose suspend functions from the ViewModel to the View. The ViewModel should expose `StateFlow` or `SharedFlow` that the View observes.
### 5. Mutable State Encapsulation
* **NEVER** expose `MutableStateFlow` or `MutableSharedFlow` publicly.
* Expose them as read-only `StateFlow` or `Flow` using `.asStateFlow()` or upcasting.
### 6. GlobalScope Prohibition
* **NEVER** use `GlobalScope`. It breaks structured concurrency and leads to leaks.
* If a task must survive the current scope, use an injected `applicationScope` (a custom scope tied to the Application lifecycle).
### 7. Exception Handling
* **NEVER** catch `CancellationException` in a generic `catch (e: Exception)` block without rethrowing it.
* Use `runCatching` only if you explicitly rethrow `CancellationException`.
* Use `CoroutineExceptionHandler` only for top-level coroutines (inside `launch`). It has no effect inside `async` or child coroutines.
### 8. Cancellability
* Coroutines feature **cooperative cancellation**. They don't stop immediately unless they check for cancellation.
* **ALWAYS** call `ensureActive()` or `yield()` in tight loops (e.g., processing a large list, reading files) to check for cancellation.
* Standard functions like `delay()` and `withContext()` are already cancellable.
### 9. Callback Conversion
* Use `callbackFlow` to convert callback-based APIs to Flow.
* **ALWAYS** use `awaitClose` at the end of the `callbackFlow` block to unregister listeners.
## Code Patterns
### Repository Pattern with Flow
```kotlin
class NewsRepository(
private val remoteDataSource: NewsRemoteDataSource,
private val externalScope: CoroutineScope, // For app-wide events
private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
) {
val newsUpdates: Flow<List<News>> = flow {
val news = remoteDataSource.fetchLatestNews()
emit(news)
}.flowOn(ioDispatcher) // Upstream executes on IO
}
```
### Parallel Execution
```kotlin
suspend fun loadDashboardData() = coroutineScope {
val userDeferred = async { userRepo.getUser() }
val feedDeferred = async { feedRepo.getFeed() }
// Wait for both
DashboardData(
user = userDeferred.await(),
feed = feedDeferred.await()
)
}
```
### Testing with runTest
```kotlin
@Test
fun testViewModel() = runTest {
val testDispatcher = StandardTestDispatcher(testScheduler)
val viewModel = MyViewModel(testDispatcher)
viewModel.loadData()
advanceUntilIdle() // Process coroutines
assertEquals(expectedState, viewModel.uiState.value)
}
```
---
**Source:** [`new-silvermoon/awesome-android-agent-skills`](https://github.com/new-silvermoon/awesome-android-agent-skills) → `.github/skills/concurrency_and_networking/android-coroutines/SKILL.md`
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!