kotlin-flow

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Kotlin Flow Skill

Kotlin Flow 技能

Reactive programming with Kotlin Flow.
使用Kotlin Flow进行响应式编程。

Topics Covered

涵盖主题

Cold vs Hot Flows

冷流与热流

kotlin
// 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()
kotlin
// 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

Flow操作符

kotlin
fun searchUsers(query: Flow<String>): Flow<List<User>> =
    query
        .debounce(300)
        .filter { it.length >= 2 }
        .distinctUntilChanged()
        .flatMapLatest { term -> userRepository.search(term) }
        .catch { emit(emptyList()) }
kotlin
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

合并Flow

kotlin
val dashboard: Flow<Dashboard> = combine(
    userFlow,
    ordersFlow,
    notificationsFlow
) { user, orders, notifications ->
    Dashboard(user, orders.size, notifications.count())
}
kotlin
val dashboard: Flow<Dashboard> = combine(
    userFlow,
    ordersFlow,
    notificationsFlow
) { user, orders, notifications ->
    Dashboard(user, orders.size, notifications.count())
}

Testing with Turbine

使用Turbine进行测试

kotlin
@Test
fun `flow emits values`() = runTest {
    viewModel.state.test {
        assertThat(awaitItem().isLoading).isFalse()
        viewModel.load()
        assertThat(awaitItem().isLoading).isTrue()
        advanceUntilIdle()
        assertThat(awaitItem().data).isNotNull()
    }
}
kotlin
@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

问题排查

IssueResolution
Flow never emitsAdd terminal operator (collect, first)
Stale data in UIUse stateIn or shareIn properly
问题解决方法
Flow从未发射数据添加终端操作符(collect、first)
UI中数据过时正确使用stateIn或shareIn

Usage

使用方法

Skill("kotlin-flow")
Skill("kotlin-flow")