Kotlin Flow 深度探索与实践指南——下部:进阶与精通篇

23 阅读2分钟

 第五部分:Flow 进阶原理

第13章:Flow 背压机制深度对比

13.1 Flow (冷流):灵活但需手动配置的背压

文案总结
冷流每次收集时从头开始执行,适合数据转换管道,但需要手动管理背压问题。当生产速度 > 消费速度时,需要选择合适的背压策略。

13.1.1 背压三剑客对比分析

对比表格

策略原理适用场景数据丢失情况
buffer建立缓冲区,生产消费并行文件下载、批量处理不丢失
conflate丢弃中间值,只保留最新UI状态更新、传感器数据丢弃中间值
collectLatest新值到来时取消当前处理搜索建议、可取消操作丢弃未完成值

代码示例

kotlin

// 1. buffer示例:建立缓冲区
flow {
    repeat(5) { i ->
        delay(50)
        emit(i)
    }
}.buffer(2)  // 容量为2的缓冲区
 .collect { delay(100); println(it) }

// 2. conflate示例:只保留最新
flow {
    repeat(5) { i ->
        delay(30)
        emit(i)
    }
}.conflate()  // 丢弃中间值
 .collect { delay(100); println(it) }

// 3. collectLatest示例:可取消处理
flow {
    repeat(5) { i ->
        delay(50)
        emit(i)
    }
}.collectLatest {  // 新值到来取消当前
    println("开始: $it")
    delay(200)
    println("完成: $it")
}

场景选择指南

  • 实时监控:conflate(只关心最新)
  • 数据备份:buffer(不能丢失)
  • 用户输入:collectLatest(可取消)
13.2 StateFlow:永不挂起,丢弃中间值的策略

文案总结
StateFlow是热流,保存当前状态,自动去重。快速更新时丢弃中间值,emit(value)永不挂起,适合UI状态管理。

代码示例

kotlin

// StateFlow特性演示
val stateFlow = MutableStateFlow(0)

// 生产者快速更新
launch {
    repeat(10) {
        stateFlow.value = it  // 永不挂起,中间值被丢弃
        delay(10)
    }
}

// 消费者慢速收集
launch {
    stateFlow.collect {
        println("收到: $it")
        delay(100)
    }
}
13.3 SharedFlow:高度可配,支持挂起或丢弃

文案总结
SharedFlow是热流,无当前状态概念,可配置缓冲区大小和背压策略(SUSPEND或DROP)。适合事件总线。

代码示例

kotlin

// SharedFlow配置示例
val sharedFlow = MutableSharedFlow<String>(
    replay = 1,  // 新订阅者获取最新1个值
    extraBufferCapacity = 10,  // 额外缓冲区
    onBufferOverflow = BufferOverflow.DROP_OLDEST  // 满时丢弃最旧
)

// 发射可能挂起(如果缓冲区满且策略为SUSPEND)
launch {
    sharedFlow.emit("事件")
}
13.4 性能陷阱与优化
13.4.1 flatMap的滥用问题

文案总结
flatMap每次发射创建新流,导致内存和性能问题。应使用map + flattenMerge控制并发数。

代码示例

kotlin

// ❌ 错误:频繁创建流
flowOf("a", "b", "c")
    .flatMapConcat { search(it) }

// ✅ 优化:控制并发
flowOf("a", "b", "c")
    .map { search(it) }
    .flattenMerge(concurrency = 2)  // 限制并发数
13.4.2 线程切换成本分析

文案总结
每个flowOn创建新协程,增加上下文切换开销。应合并连续flowOn调用。

代码示例

kotlin

// ❌ 频繁切换
flow { emit(1) }
    .flowOn(Dispatchers.IO)
    .map { it * 2 }
    .flowOn(Dispatchers.Default)  // 不必要的切换

// ✅ 合并切换
flow { 
    withContext(Dispatchers.IO) {
        emit(1)
    }
}.flowOn(Dispatchers.IO)  // 只切换一次
13.4.3 内存泄漏排查

文案总结
未取消的协程导致内存泄漏。使用lifecycleScope,及时取消协程,避免GlobalScope。

代码示例

kotlin

class SafeViewModel : ViewModel() {
    fun collectSafely() {
        viewModelScope.launch {  // ✅ 随ViewModel清理
            flow.collect {
                // 处理数据
            }
        }
    }
}
13.4.4 CPU使用率优化

文案总结
避免繁忙循环,添加延迟,使用批处理减少操作次数。

代码示例

kotlin

// ❌ 繁忙循环,高CPU
flow {
    while (true) {
        emit(data)
    }
}

// ✅ 添加延迟,降低CPU
flow {
    while (true) {
        emit(data)
        delay(16)  // ~60FPS
    }
}
13.5 场景分析:如何为不同场景选择最优背压策略?

决策树

  1. 数据能否丢失?

    • 不能 → buffer
    • 能 → 继续
  2. 只关心最新吗?

    • 是 → conflate
    • 否 → collectLatest
  3. 操作可取消吗?

    • 是 → collectLatest
    • 否 → 无特殊策略

代码示例

kotlin

// 搜索场景:collectLatest
searchFlow.collectLatest { query ->
    val results = searchApi(query)
    updateUI(results)
}

// 下载场景:buffer
downloadFlow.buffer(3)  // 并发下载3个文件

// 状态更新:conflate
sensorDataFlow.conflate()  // 只更新最新读数

第14章:Channel:Flow的底层通信管道

14.1 Channel vs. Flow:为何Google推荐优先使用Flow?

对比表格

特性ChannelFlow (推荐)
编程模型命令式声明式
背压支持基本丰富策略
操作符丰富(map、filter等)
内存安全易泄漏冷流更安全

代码示例

kotlin

// Flow优先
flow { emit(1); emit(2) }
    .map { it * 2 }
    .collect { println(it) }

// Channel特定场景
val channel = Channel<Int>()
launch { channel.send(1) }
launch { println(channel.receive()) }
14.2 Channel的适用场景:协程间的安全通信

文案总结
Channel适合精确控制背压、工作队列、协程间双向通信。

代码示例

kotlin

// 工作队列模式
val taskChannel = Channel<Task>()
repeat(3) { workerId ->
    launch {
        for (task in taskChannel) {
            processTask(task)
        }
    }
}

// 请求-响应模式
val requestChannel = Channel<Request>()
val responseChannel = Channel<Response>()

第15章:Flow内部实现探秘

15.1 emit-collect的调用链路与SafeCollector

文案总结
SafeCollector包装原始收集器,确保emit在正确上下文调用,防止线程安全问题。

代码示例

kotlin

// 简化流程
flow {
    emit(1)  // → SafeCollector → 原始collector
}.collect { println(it) }
15.2 flowOn()如何实现上下文切换

文案总结
flowOn创建新协程,在新上下文中收集,通过SafeCollector切回原上下文发射。

代码示例

kotlin

flow { emit(1) }
    .flowOn(Dispatchers.IO)  // 创建IO协程收集
    .collect {  // 在主线程收集
        println(it)
    }
15.3 StateFlow如何通过CAS操作保证并发安全

文案总结
StateFlow使用AtomicReference和CAS操作保证并发更新安全,自动去重。

代码示例

kotlin

// 简化CAS操作
var value = 0
fun update(newValue: Int) {
    while (true) {
        val current = value
        if (current == newValue) return  // 去重
        if (compareAndSet(current, newValue)) break
    }
}

第16章:性能优化与自定义操作符

16.1 性能优化技巧

检查清单
✅ 使用lifecycleScope/viewModelScope
✅ 合并flowOn调用
✅ 避免flatMap滥用
✅ 及时取消协程
✅ 使用合适的缓冲区大小

代码示例

kotlin

// 综合优化
viewModelScope.launch {
    dataSource()
        .flowOn(Dispatchers.IO)  // 合并IO操作
        .buffer(50)  // 合理缓冲区
        .collect { updateUI(it) }
}
16.2 自定义Flow操作符

文案总结
通过扩展函数创建自定义操作符,封装业务逻辑,提高代码复用性。

代码示例

kotlin

// 自定义防抖操作符
fun <T> Flow<T>.debounceFirst(timeout: Long): Flow<T> = flow {
    var lastEmitTime = 0L
    collect { value ->
        val now = System.currentTimeMillis()
        if (now - lastEmitTime >= timeout) {
            emit(value)
            lastEmitTime = now
        }
    }
}

// 使用
flow { emit(1); emit(2) }
    .debounceFirst(100)
    .collect()

📊 第六部分:测试与质量保障

第17章:测试你的Flow

17.1 使用kotlinx-coroutines-test和Turbine库

文案总结
测试Flow需要特殊工具,因为Flow是异步的。Turbine提供Flow测试DSL。

代码示例

kotlin

dependencies {
    testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4")
    testImplementation("app.cash.turbine:turbine:0.12.1")
}
17.2 单元测试:测试普通Flow、StateFlow与SharedFlow

代码示例

kotlin

@Test
fun `测试普通Flow`() = runTest {
    flowOf(1, 2, 3).test {
        assertEquals(1, awaitItem())
        assertEquals(2, awaitItem())
        assertEquals(3, awaitItem())
        awaitComplete()
    }
}

@Test
fun `测试StateFlow`() = runTest {
    val stateFlow = MutableStateFlow(0)
    
    // 测试初始值
    assertEquals(0, stateFlow.value)
    
    // 测试更新
    stateFlow.value = 1
    assertEquals(1, stateFlow.value)
}

@Test
fun `测试SharedFlow`() = runTest {
    val sharedFlow = MutableSharedFlow<Int>()
    
    // 收集流
    val values = mutableListOf<Int>()
    val job = launch {
        sharedFlow.collect { values.add(it) }
    }
    
    // 发射值
    sharedFlow.emit(1)
    sharedFlow.emit(2)
    
    // 等待收集完成
    advanceUntilIdle()
    
    // 验证
    assertEquals(listOf(1, 2), values)
    job.cancel()
}
17.3 集成测试与UI测试策略

文案总结
集成测试验证多个组件协作,UI测试验证Flow是否正确更新界面。

代码示例

kotlin

// ViewModel集成测试
@Test
fun `测试ViewModel与Flow集成`() = runTest {
    val viewModel = MyViewModel()
    
    // 触发操作
    viewModel.fetchData()
    
    // 验证状态变化
    viewModel.uiState.test {
        assertEquals(Loading, awaitItem())
        val success = awaitItem() as Success
        assertEquals(3, success.data.size)
    }
}

// Compose UI测试
@Test
fun `测试Compose UI更新`() = runComposeTest {
    val viewModel = MyViewModel()
    
    setContent {
        val state by viewModel.state.collectAsState()
        Text(text = state)
    }
    
    // 验证初始状态
    onNodeWithText("初始").assertExists()
    
    // 更新状态并验证
    viewModel.updateState("新状态")
    onNodeWithText("新状态").assertExists()
}

第18章:调试与监控

18.1 Coroutine Debugger与日志技巧

文案总结
使用协程调试器查看协程状态,添加CoroutineName便于日志跟踪。

代码示例

kotlin

// 添加协程名称
launch(CoroutineName("数据加载")) {
    flow.collect {
        println("${coroutineContext[CoroutineName]?.name}: 收到 $it")
    }
}

// 调试技巧
val flow = flow {
    println("Flow开始执行")
    emit(1)
    println("Flow继续执行")
}.onEach {
    println("中间处理: $it")
}
18.2 性能监控与分析

文案总结
使用Android Profiler监控内存、CPU、网络,添加自定义监控点。

代码示例

kotlin

// 简单性能监控
class FlowMonitor {
    fun <T> monitor(flow: Flow<T>, name: String): Flow<T> = flow {
        val startTime = System.currentTimeMillis()
        var count = 0
        
        flow.collect { value ->
            count++
            emit(value)
        }
        
        val duration = System.currentTimeMillis() - startTime
        println("[$name] 处理 $count 项,耗时 ${duration}ms")
    }
}

// 使用
flow { emit(1); emit(2) }
    .monitor("测试流")
    .collect()

📋 快速参考表

背压策略速查

场景策略代码
完整数据buffer.buffer(50)
UI更新conflate.conflate()
搜索建议collectLatest.collectLatest { }
事件总线SharedFlowMutableSharedFlow()
状态管理StateFlowMutableStateFlow()

测试代码模板

kotlin

// Flow测试模板
@Test
fun `Flow基本测试`() = runTest {
    flow { /* 构建数据 */ }
        .test {
            // 验证每个值
            assertEquals(expected1, awaitItem())
            assertEquals(expected2, awaitItem())
            
            // 验证完成
            awaitComplete()
        }
}

这个完整指南涵盖了Flow的核心概念、性能优化、测试策略和调试技巧,每个部分都提供了简洁的文案总结和实用的代码示例。

第19章:Flow 十大反模式清单

📉 19.1 生命周期泄漏:launchWhenX 的陷阱与正确解决方案

问题描述
使用 launchWhenStartedlaunchWhenResumed 等函数会导致协程在生命周期状态变化时重复启动和停止,造成资源浪费和状态不一致。

错误代码

kotlin

// ❌ 反模式:使用 launchWhenX
class LeakyViewModel : ViewModel() {
    init {
        lifecycleScope.launchWhenStarted {
            flow.collect { updateUI(it) } // 每次恢复都会重新收集
        }
    }
}

正确解决方案

kotlin

// ✅ 正确模式:使用 repeatOnLifecycle
class SafeViewModel : ViewModel() {
    fun observeWithLifecycle(lifecycle: Lifecycle) {
        lifecycleScope.launch {
            lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
                flow.collect { updateUI(it) } // 自动取消和重启
            }
        }
    }
}

📉 19.2 过度使用 flatMap:性能杀手与替代方案

问题描述
flatMapConcat 每次发射都创建新流,导致大量协程和内存开销,尤其是在高频数据流中。

错误代码

kotlin

// ❌ 反模式:每个值都创建新流
flow {
    emit("query1")
    emit("query2")
}.flatMapConcat { query ->
    networkRequestFlow(query) // 每次发射都创建新流
}

正确解决方案

kotlin

// ✅ 正确模式:控制并发数
flow {
    emit("query1")
    emit("query2")
}.map { query ->
    networkRequestFlow(query)
}.flattenMerge(concurrency = 2) // 限制并发数

📉 19.3 错误的重试策略:无限重试与指数退避的正确使用

问题描述
简单重试或无限重试可能导致死循环或过多资源消耗。

错误代码

kotlin

// ❌ 反模式:无限重试
flow {
    emit(data)
}.retry { true } // 永远重试

// ❌ 反模式:立即重试
.retry(3) // 立即重试3次,可能导致雪崩

正确解决方案

kotlin

// ✅ 正确模式:指数退避重试
fun <T> Flow<T>.retryWithBackoff(
    maxRetries: Int = 3,
    initialDelay: Long = 1000
): Flow<T> = flow {
    var currentDelay = initialDelay
    var retryCount = 0
    
    collect { value -> emit(value) }
}.catch { e ->
    if (retryCount++ < maxRetries) {
        delay(currentDelay)
        currentDelay *= 2 // 指数退避
        emitAll(this@retryWithBackoff) // 重新收集
    } else {
        throw e
    }
}

📉 19.4 线程切换混乱:flowOn 多次调用的副作用

问题描述
多个 flowOn 调用创建多个协程层,增加上下文切换开销。

错误代码

kotlin

// ❌ 反模式:不必要的多次切换
flow {
    emit(1) // IO线程
}
.flowOn(Dispatchers.IO)
.map { it * 2 } // Default线程
.flowOn(Dispatchers.Default)
.filter { it > 0 } // IO线程
.flowOn(Dispatchers.IO)

正确解决方案

kotlin

// ✅ 正确模式:合并线程切换
flow {
    // 所有IO操作集中处理
    withContext(Dispatchers.IO) {
        emit(1)
        // 其他IO操作...
    }
}
.flowOn(Dispatchers.IO) // 只切换一次
.map { it * 2 }
.filter { it > 0 }

📉 19.5 状态管理不当:MutableStateFlow 暴露给UI层

问题描述
直接将 MutableStateFlow 暴露给UI层,允许UI直接修改状态,破坏单向数据流。

错误代码

kotlin

// ❌ 反模式:MutableStateFlow 公开
class BadViewModel : ViewModel() {
    val count = MutableStateFlow(0) // UI可以直接修改
    
    fun increment() {
        count.value++ // ViewModel应该控制所有状态更新
    }
}

正确解决方案

kotlin

// ✅ 正确模式:暴露只读 StateFlow
class GoodViewModel : ViewModel() {
    private val _count = MutableStateFlow(0)
    val count: StateFlow<Int> = _count.asStateFlow() // 只读
    
    fun increment() {
        _count.value++ // 只有ViewModel可以修改
    }
}

// UI层只能收集,不能修改
viewModel.count.collect { updateUI(it) }

📉 19.6 事件重复消费:SharedFlow 配置错误导致事件被多次处理

问题描述
SharedFlow 配置不当可能导致事件被多个观察者重复消费,或新订阅者收到旧事件。

错误代码

kotlin

// ❌ 反模式:replay 配置不当
val events = MutableSharedFlow<Event>(
    replay = 10 // 新订阅者会收到10个旧事件
)

// ❌ 反模式:多个观察者都处理相同事件
events.collect { handleEvent(it) } // 观察者1
events.collect { handleEvent(it) } // 观察者2:重复处理

正确解决方案

kotlin

// ✅ 正确模式:根据场景配置 SharedFlow

// 场景1:事件只消费一次
val singleConsumerEvents = MutableSharedFlow<Event>(
    replay = 0, // 不重播给新订阅者
    extraBufferCapacity = 1
)

// 场景2:每个订阅者独立处理
val broadcastEvents = MutableSharedFlow<Event>().broadcastIn(viewModelScope)

// 使用唯一标识避免重复处理
events.distinctUntilChanged { it.id }.collect { handleEvent(it) }

📉 19.7 背压处理错误:错误选择 buffer、conflate、collectLatest

问题描述
背压策略选择不当导致数据丢失、性能问题或用户体验不佳。

错误代码

kotlin

// ❌ 反模式:搜索使用 buffer(用户看到过时结果)
searchFlow.buffer().collect { showResults(it) }

// ❌ 反模式:传感器数据使用 collectLatest(频繁取消导致抖动)
sensorFlow.collectLatest { updateChart(it) }

// ❌ 反模式:下载进度使用 conflate(丢失中间进度)
downloadFlow.conflate().collect { updateProgress(it) }

正确解决方案

kotlin

// ✅ 正确模式:根据数据特性选择策略

// 搜索:collectLatest(用户需要最新结果)
searchFlow.collectLatest { showLatestResults(it) }

// 传感器:conflate(只关心最新读数)
sensorFlow.conflate().collect { updateLatestReading(it) }

// 下载:buffer(需要完整进度)
downloadFlow.buffer().collect { updateAllProgress(it) }

📉 19.8 资源未释放:Flow 收集未取消导致的资源泄漏

问题描述
Flow 收集未正确取消,导致后台持续运行,消耗资源。

错误代码

kotlin

// ❌ 反模式:未管理收集协程
class LeakyService {
    init {
        // 收集协程未保存引用
        flow.collect { process(it) } // 无法取消
    }
    
    // ❌ 使用 GlobalScope
    GlobalScope.launch {
        flow.collect { process(it) } // 生命周期不受控
    }
}

正确解决方案

kotlin

// ✅ 正确模式:管理收集生命周期
class SafeService {
    private var collectionJob: Job? = null
    
    fun startCollecting() {
        collectionJob?.cancel() // 取消之前的收集
        collectionJob = lifecycleScope.launch {
            flow.collect { process(it) }
        }
    }
    
    fun stopCollecting() {
        collectionJob?.cancel()
        collectionJob = null
    }
    
    override fun onDestroy() {
        super.onDestroy()
        collectionJob?.cancel() // 确保清理
    }
}

📉 19.9 测试不充分:缺少对 Flow 超时、异常场景的测试

问题描述
只测试正常流程,忽略异常、超时、边界条件等场景。

错误代码

kotlin

// ❌ 反模式:只测试正常情况
@Test
fun testFlow() = runTest {
    flowOf(1, 2, 3).test {
        assertEquals(1, awaitItem())
        assertEquals(2, awaitItem())
        assertEquals(3, awaitItem())
        // 缺少超时、异常测试
    }
}

正确解决方案

kotlin

// ✅ 正确模式:全面测试各种场景
@Test
fun `测试Flow正常情况`() = runTest {
    flowOf(1, 2, 3).test {
        assertEquals(1, awaitItem())
        assertEquals(2, awaitItem())
        assertEquals(3, awaitItem())
        awaitComplete()
    }
}

@Test
fun `测试Flow超时`() = runTest {
    // 测试超时行为
    assertTimeout(1000) {
        slowFlow.test { /* ... */ }
    }
}

@Test
fun `测试Flow异常`() = runTest {
    flow { throw RuntimeException("错误") }
        .test {
            assertFailsWith<RuntimeException> { awaitItem() }
        }
}

@Test
fun `测试Flow空流`() = runTest {
    emptyFlow<Int>().test {
        awaitComplete() // 应该立即完成
    }
}

📉 19.10 架构设计缺陷:混淆状态与事件的边界

问题描述
将状态(State)和事件(Event)混用同一个 Flow,导致逻辑混乱。

错误代码

kotlin

// ❌ 反模式:状态和事件混用
class ConfusedViewModel : ViewModel() {
    private val _uiState = MutableStateFlow<UiModel>()
    val uiState: StateFlow<UiModel> = _uiState
    
    fun showMessage(text: String) {
        // 将事件作为状态更新
        _uiState.value = _uiState.value.copy(
            message = text,
            showMessage = true
        )
        
        // 需要手动重置状态
        delay(3000)
        _uiState.value = _uiState.value.copy(
            showMessage = false
        )
    }
}

正确解决方案

kotlin

// ✅ 正确模式:状态和事件分离
class ClearViewModel : ViewModel() {
    // 状态:当前UI状态
    private val _uiState = MutableStateFlow(UiState())
    val uiState: StateFlow<UiState> = _uiState
    
    // 事件:一次性事件
    private val _events = MutableSharedFlow<UiEvent>()
    val events: SharedFlow<UiEvent> = _events.asSharedFlow()
    
    fun showMessage(text: String) {
        // 发送事件
        viewModelScope.launch {
            _events.emit(ShowMessageEvent(text))
        }
    }
    
    fun updateData(data: Data) {
        // 更新状态
        _uiState.value = _uiState.value.copy(
            data = data,
            isLoading = false
        )
    }
}

// 事件定义
sealed class UiEvent {
    data class ShowMessageEvent(val text: String) : UiEvent()
    object NavigateToNextScreen : UiEvent()
}

// UI层处理
viewModel.events.collect { event ->
    when (event) {
        is ShowMessageEvent -> showToast(event.text)
        NavigateToNextScreen -> navigate()
    }
}

📋 反模式检查清单

反模式症状修复方案
生命周期泄漏重复收集、资源浪费使用 repeatOnLifecycle
过度使用 flatMap内存过高、性能差使用 flattenMerge 控制并发
错误重试策略无限循环、资源耗尽实现指数退避重试
线程切换混乱上下文切换开销大合并 flowOn 调用
状态管理不当UI可以直接修改状态暴露只读 StateFlow
事件重复消费同一事件处理多次合理配置 SharedFlow
背压处理错误数据丢失或响应慢根据场景选择策略
资源未释放后台持续运行管理收集协程生命周期
测试不充分生产环境出现意外增加边界条件测试
架构设计缺陷状态事件混淆分离 StateFlow 和 SharedFlow

🛠️ 代码质量检查工具

kotlin

// 简单的反模式检测器
object FlowAntiPatternDetector {
    fun analyzeFlow(flow: Flow<*>): List<String> {
        val warnings = mutableListOf<String>()
        
        // 检测 flatMap 滥用
        if (flow.toString().contains("flatMapConcat")) {
            warnings.add("⚠️ 检测到 flatMapConcat,考虑使用 flattenMerge")
        }
        
        // 检测多个 flowOn
        val flowOnCount = flow.toString().count { it == "flowOn" }
        if (flowOnCount > 1) {
            warnings.add("⚠️ 检测到 $flowOnCount 个 flowOn,考虑合并")
        }
        
        return warnings
    }
}

// 使用示例
val warnings = FlowAntiPatternDetector.analyzeFlow(myFlow)
warnings.forEach { println(it) }

🔧 最佳实践速查

kotlin

// 模板:安全的数据流架构
class BestPracticeViewModel : ViewModel() {
    // 1. 状态管理:只读暴露
    private val _state = MutableStateFlow(initialState)
    val state: StateFlow<State> = _state.asStateFlow()
    
    // 2. 事件管理:一次性事件
    private val _events = MutableSharedFlow<Event>(
        replay = 0,
        extraBufferCapacity = 10
    )
    val events: SharedFlow<Event> = _events.asSharedFlow()
    
    // 3. 安全的流收集
    private var collectionJobs = mutableMapOf<String, Job>()
    
    fun startFlowCollection(name: String, flow: Flow<*>) {
        collectionJobs[name]?.cancel()
        collectionJobs[name] = viewModelScope.launch {
            flow.collect { /* 处理 */ }
        }
    }
    
    fun stopFlowCollection(name: String) {
        collectionJobs[name]?.cancel()
        collectionJobs.remove(name)
    }
    
    // 4. 生命周期管理
    override fun onCleared() {
        collectionJobs.values.forEach { it.cancel() }
        super.onCleared()
    }
}