Kotlin Flow 开发应用实践之搜索优化

3,463 阅读1分钟

一. 问题引出 现在几乎所有的 App 都有搜索功能 , 一般情况我们监听 EditText 控件,当值发生改变去请求搜索接口. 如:

    etSearch.doOnTextChanged { text, start, before, count ->
            search(text.toString())
        }

这样就会出现两个问题:

  • 可能导致很多没有意义的请求,耗费用户流量(因为控件的值每更改一次立即就会去请求网络,而且只是最后输入的关键字是有用的)
  • 可能导致最终搜索的结果不是用户想要的. 例如,用户一开始输入关键字 AB 这个时候出现两个请求, 一个请求是 A 关键字, 一个请求是 AB 关键字. 表面上是 A 请求先发出去, AB 请求后发出去. 如果后发出去的 AB 请求先返回, A 请求后返回,那么 A 请求后的结果将会覆盖 AB 请求的结果. 从而导致搜索结果不正确.

二. 解决问题 使用Kotlin Flow 的 debounce,flatMapLatest等操作符可以解决这个问题。

val stateFlow = MutableStateFlow("")
private fun searchFilter(){
  	stateFlow
                .debounce(500)
                .filter {
                    it.isNotEmpty()
                }
                .flatMapLatest {
                    getFlowList(it)
                }
                .catch { print(it.message) }
                .flowOn(Dispatchers.Default)
                .onEach {
                    print(it.toString())
                }.flowOn(Dispatchers.Main)
                .launchIn(lifecycleScope)
}

上面代码的主要逻辑:

  • stateFlow:一个状态容器式可观察数据流,可以向其收集器发出当前状态更新和新状态更新
  • 使用 debounce 操作符:只有允许间隔超过500ms间隔才能触发,避免过多的请求
  • 使用 filter 操作符: 只有关键词不为空才进行请求,避免空的输入值也请求
  • 使用 flatMap 操作符:如果前面的请求没有完成,直接取消,然后开始先的请求
  • 使用 catch 操作符:捕获异常,释放空的List

Demo地址