From android
Authoritative rules and patterns for production-quality Kotlin Coroutines onto Android. Covers structured concurrency, lifecycle integration, and reactive streams.
How this skill is triggered — by the user, by Claude, or both
Slash command
/android:android-coroutinesThe summary Claude sees in its skill listing — used to decide when to auto-load this 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).
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).
Flow, StateFlow, SharedFlow, and callbackFlow.viewModelScope, lifecycleScope) and safe collection (repeatOnLifecycle).CoroutineExceptionHandler, SupervisorJob, and proper try-catch hierarchies.ensureActive().TestDispatcher and runTest.Activate this skill when the user asks to:
Dispatchers.IO, Dispatchers.Default) inside classes.CoroutineDispatcher via the constructor.Dispatchers.IO in the constructor argument for convenience, but allow it to be overridden.// CORRECT
class UserRepository(
private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
) { ... }
// INCORRECT
class UserRepository {
fun getData() = withContext(Dispatchers.IO) { ... }
}
suspend functions.Flow.Dispatchers.Main without blocking the UI.withContext(dispatcher) inside the repository implementation to move execution to the background.lifecycleScope.launch or launchWhenStarted (deprecated/unsafe).repeatOnLifecycle(Lifecycle.State.STARTED) for collecting flows in Activities or Fragments.// CORRECT
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.uiState.collect { ... }
}
}
viewModelScope for initiating coroutines in ViewModels.StateFlow or SharedFlow that the View observes.MutableStateFlow or MutableSharedFlow publicly.StateFlow or Flow using .asStateFlow() or upcasting.GlobalScope. It breaks structured concurrency and leads to leaks.applicationScope (a custom scope tied to the Application lifecycle).CancellationException in a generic catch (e: Exception) block without rethrowing it.runCatching only if you explicitly rethrow CancellationException.CoroutineExceptionHandler only for top-level coroutines (inside launch). It has no effect inside async or child coroutines.ensureActive() or yield() in tight loops (e.g., processing a large list, reading files) to check for cancellation.delay() and withContext() are already cancellable.callbackFlow to convert callback-based APIs to Flow.awaitClose at the end of the callbackFlow block to unregister listeners.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
}
suspend fun loadDashboardData() = coroutineScope {
val userDeferred = async { userRepo.getUser() }
val feedDeferred = async { feedRepo.getFeed() }
// Wait for both
DashboardData(
user = userDeferred.await(),
feed = feedDeferred.await()
)
}
@Test
fun testViewModel() = runTest {
val testDispatcher = StandardTestDispatcher(testScheduler)
val viewModel = MyViewModel(testDispatcher)
viewModel.loadData()
advanceUntilIdle() // Process coroutines
assertEquals(expectedState, viewModel.uiState.value)
}
npx claudepluginhub canergulgec/mobile-dev-skills --plugin androidCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.