kotlin-flow
Kotlin Flow - StateFlow, SharedFlow, operators, testing
When & Why to Use This Skill
This Claude skill empowers developers to master reactive programming in Kotlin by providing expert implementation patterns for Kotlin Flow. It covers essential state management tools like StateFlow and SharedFlow, advanced transformation operators, and robust testing methodologies using Turbine. By streamlining asynchronous data stream handling, it helps build more responsive, thread-safe, and maintainable Android and Kotlin applications.
Use Cases
- State Management in Android: Implementing StateFlow within ViewModels to manage UI state in a lifecycle-aware and thread-safe manner.
- User Input Optimization: Applying operators like debounce, filter, and flatMapLatest to handle real-time search queries and reduce unnecessary API overhead.
- Complex Data Orchestration: Combining multiple asynchronous data sources (e.g., user profiles, orders, and notifications) into a single, unified stream for dashboard displays.
- Reliable Unit Testing: Utilizing the Turbine library and runTest to validate flow emissions, ensuring that reactive logic behaves correctly under various conditions.
| name | kotlin-flow |
|---|---|
| description | Kotlin Flow - StateFlow, SharedFlow, operators, testing |
| version | "1.0.0" |
| sasmp_version | "1.3.0" |
| bonded_agent | 03-kotlin-coroutines |
| bond_type | PRIMARY_BOND |
| timeout_ms | 30000 |
| max_attempts | 3 |
| backoff | exponential |
| initial_delay_ms | 1000 |
| - name | include_examples |
| type | boolean |
| validation | "^(basics|operators|hot_flows|testing)$" |
| default | true |
| level | info |
| events | [skill_invoked, topic_loaded, error_occurred] |
Kotlin Flow Skill
Reactive programming with Kotlin Flow.
Topics Covered
Cold vs Hot Flows
// Cold Flow - starts fresh for each collector
fun loadData(): Flow<Data> = flow {
emit(fetchData())
}
// Hot Flow - shared state
private val _state = MutableStateFlow(State())
val state: StateFlow<State> = _state.asStateFlow()
Flow Operators
fun searchUsers(query: Flow<String>): Flow<List<User>> =
query
.debounce(300)
.filter { it.length >= 2 }
.distinctUntilChanged()
.flatMapLatest { term -> userRepository.search(term) }
.catch { emit(emptyList()) }
Combining Flows
val dashboard: Flow<Dashboard> = combine(
userFlow,
ordersFlow,
notificationsFlow
) { user, orders, notifications ->
Dashboard(user, orders.size, notifications.count())
}
Testing with Turbine
@Test
fun `flow emits values`() = runTest {
viewModel.state.test {
assertThat(awaitItem().isLoading).isFalse()
viewModel.load()
assertThat(awaitItem().isLoading).isTrue()
advanceUntilIdle()
assertThat(awaitItem().data).isNotNull()
}
}
Troubleshooting
| Issue | Resolution |
|---|---|
| Flow never emits | Add terminal operator (collect, first) |
| Stale data in UI | Use stateIn or shareIn properly |
Usage
Skill("kotlin-flow")