Kotlin Flow批量上传触发事件丢失:寻求纯Flow优雅实现方案
优雅实现多触发场景的Flow批量上传方案
针对你的三个触发场景(数据达批量大小、定时触发、应用内事件触发),可以通过**channelFlow**实现纯Flow风格的优雅方案,既避免Channel的多Job冗余,又保证触发信号不丢失:
private val databaseFlow = dataSource.getEventBatchStream(batchSize) private val timerFlow = TickerFlowFactory().createTickerFlow() private val userRequestFlow = MutableSharedFlow<Unit>(extraBufferCapacity = 1) // 替换StateFlow避免conflation // 统一创建触发Flow private val uploadTriggerFlow = channelFlow { // 收集数据库批量触发信号 launch { databaseFlow .filter { it.size == batchSize } .collect { send(Unit) } } // 收集定时触发信号 launch { timerFlow.collect { send(Unit) } } // 收集用户请求触发信号 launch { userRequestFlow.collect { send(Unit) } } } saveJob = scope.launch { uploadTriggerFlow.collect { saveEventBatch(dataSource.getEventBatch(batchSize)) } }
方案说明:
- 替换StateFlow为MutableSharedFlow:StateFlow是conflated类型的Flow,多次发送相同值会被合并覆盖。改用
extraBufferCapacity=1的SharedFlow可保留每次触发信号,避免丢失。 - channelFlow统一管理触发源:通过
channelFlow内部启动协程分别收集三个触发流,所有触发信号都会通过send转发到同一个Flow中,保证每个信号都能被处理。 - 简化Job管理:相比之前的Channel方案,无需为每个触发源单独创建Job,所有收集逻辑封装在
channelFlow内部,完全符合Flow的惯用写法。
如果需要避免无意义的上传(比如刚上传完数据库已无数据),可以在saveEventBatch中判断获取的批量数据是否为空,为空则直接返回。
内容的提问来源于stack exchange,提问作者Zachary Sweigart
相关产品推荐
相关产品推荐

