如何高效合并并缓存两个Kotlin Flow以避免重复网络请求?
问题
我有两个无法修改的库函数:
fun list(): Flow<List<ID>>
和
fun propertiesById(id: ID): Flow<List<Prop>>
需求是将二者合并,获取ID及其所有属性的完整信息(属性可能会更新)。
目前的实现如下:
val result = list().flatMapLatest { ids -> val propFlow = ids.map { id -> propertiesById(id).map { props -> MyClass(id, props) } } combine(propFlow) { it.toList() } }
该实现能正常返回Flow<List<MyClass>>,但存在效率问题:每当ID列表新增或移除元素时,对应的propertiesById Flow会被取消并重新创建,而这个Flow涉及网络请求,反复重建会大幅降低性能。
请问是否有办法缓存propertiesById的Flow,使得ID列表更新时,能复用已有的Flow,避免反复取消和创建?
解决方案
核心思路是缓存每个ID对应的propertiesById Flow实例,当ID列表更新时,只对新增的ID创建新Flow,对保留的ID复用已有Flow,对移除的ID清理对应的Flow。
可以通过一个映射表维护缓存,结合transformLatest操作符处理ID列表的更新:
// 缓存每个ID对应的Flow,确保同一个ID只创建一次Flow实例 private val idFlowCache = mutableMapOf<ID, Flow<MyClass>>() val result = list().transformLatest { currentIds -> // 1. 清理已移除的ID对应的缓存 val removedIds = idFlowCache.keys - currentIds removedIds.forEach { id -> idFlowCache.remove(id) } // 2. 为新增的ID创建Flow并加入缓存 val addedIds = currentIds - idFlowCache.keys addedIds.forEach { id -> val flow = propertiesById(id) .map { props -> MyClass(id, props) } .onCompletion { // 当Flow意外完成时自动移除缓存(可选,根据业务场景调整) idFlowCache.remove(id) } idFlowCache[id] = flow } // 3. 合并当前所有有效Flow并发射结果 val activeFlows = currentIds.mapNotNull { idFlowCache[it] } combine(activeFlows) { it.toList() } .collect { emit(it) } }
关键细节说明:
- 缓存复用:同一个ID只会触发一次
propertiesById调用,后续只要ID还在列表中,就直接复用缓存的Flow,彻底避免重复网络请求。 - 资源回收:当ID从列表中移除时,从缓存中删除对应的Flow,Kotlin Flow会在没有收集者时自动取消,释放网络连接等资源。
- 线程安全优化:如果是多线程场景,可将
mutableMapOf替换为ConcurrentHashMap,避免并发操作冲突:
private val idFlowCache = ConcurrentHashMap<ID, Flow<MyClass>>()
内容的提问来源于stack exchange,提问作者Deishelon
相关产品推荐
相关产品推荐

