过滤器变更时如何触发StateFlow重新运行并发射更新结果
问题根因
你的实现无法在filter更新时触发新结果推送,核心原因是filter是普通可变变量,它的变化不会进入Flow的观察链路。map操作符仅会在上游api.resultFlow()发射新数据时触发执行,filter修改后没有任何机制通知Flow管道重算过滤逻辑,自然不会输出新结果。
修复方案
要实现「原始列表更新、过滤关键词更新任意一个发生时,都推送最新过滤结果」的效果,需要做两个调整:
- 把普通的
filter变量改成可被Flow观察的MutableStateFlow,让过滤条件的变化也成为流事件 - 用
combine操作符同时订阅原始结果流、过滤条件流,两个流任意一个发射新值,就自动重算过滤结果
完整实现代码如下:
class ResultsViewModel( private val api: API ) : ViewModel() { // 内部持有可修改的过滤条件StateFlow private val _filter = MutableStateFlow("") val results: StateFlow<List<String>> = api.resultFlow() .combine(_filter) { sourceList, currentFilter -> // 原始列表更新/过滤词更新时,都会走到这里重算 sourceList.filter { item -> item.contains(currentFilter) } } .stateIn( scope = viewModelScope, started = SharingStarted.Eagerly, initialValue = emptyList() ) // 对外提供更新过滤条件的入口,外部调用即可触发结果重算 fun updateFilter(newKeyword: String) { _filter.value = newKeyword } }
额外说明
- 如果需要做忽略大小写的过滤,可以把
contains调用改成item.contains(currentFilter, ignoreCase = true) - 不要在Flow的转换操作符(比如
map、filter)里引用外部普通可变变量,这类变量的生命周期和Flow的收集链路无关,变化无法被Flow感知,很容易出现你遇到的不生效问题 - 上述实现中,不管是接口返回了新的原始列表,还是外部调用
updateFilter修改了搜索关键词,results都会立即发射最新的过滤后列表,满足响应式更新的要求。
内容的提问来源于stack exchange,提问作者dave mankoff
相关产品推荐
相关产品推荐

