写点什么

「正确」的使用 Kotlin Flow 进行搜索优化

发布于: 2021 年 11 月 07 日

用户搜索时,为了避免产生无意义的搜索请求,通常会进行搜索数据限流。熟悉 RxJava 的同学,一定会知道怎么做,各种天花乱坠的操作符让你眼花缭乱。


那么用上了 kotlin 的小伙伴,完全可以不必使用 RxJava,因为 kotlin 中自带的 Flow 就可以做到。不废话,直接开始。


激起我写作的原因是这一篇文章 Kotlin Flow 开发应用实践之搜索优化,这篇文章错误的使用了 Flow,目前作者已经对文章内部的错误进行了更改,但是我还是想借机来说明一下。随后给出正确的解释及正确的代码。


错在了哪


====


我先把那篇文章中错误的代码贴上来:


// 错误代码


binding.etSearch.doOnTextChanged { text, _, _, _ ->


searchFilter(text.toString())


}


private fun searchFilter(str:String){


flow { emit(str) }


.debounce(400)


.filter {


it.isNotEmpty()


}


.catch { LogUtils.d(it.message) }


.flowOn(Dispatchers.Default)


.onEach {


LogUtils.d("输出:$it")


binding.tvShow.text = it.toString()


}.flowOn(Dispatchers.Main)


.launchIn(lifecycleScope)


}


仔细看上面的代码,你们自己想想错在了哪里?


文本输入框 etSearch 每次文本的变化都会回掉 searchFilter()方法,而方法里面每次都去实例化了一个 flow,然后又使用了 debounce()限流,那么这个 debounce()限流的意义何在?毫无意义啊,对吧。因为每次都是新创建的 flow 啊。


还不懂的话,那就看下面简化的代码:


// 文章错误代码的简化


for (i in 0..100) {


// 模拟生成数据


flow<Int> {


emit(i)


}.debounce(500) // 这里是无效的 限流,因为 flow 的 emit 只执行了一次啊……


.collect {


println("----------------->>> $it")


}


}


那么我们理想中的正确代码逻辑是这样的:


flow<Int> {


for (i in 0..100) {


// 模拟生成数据


emit(i)


}


}.debounce(500) // 这里是有效的 限流


.coll


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


ect {


println("----------------->>> $it")


}


好了,同学们可以再对比以上两段代码,for 循环就是我们模拟的输入数据,这个 for 循环在里面和在外面是两个完全不一样的逻辑~不再多做解释了


正确的用法


=====


你以为的正确写法


========


对于输入框的这类业务逻辑,单纯使用 flow 是无法到达目的的,因为写不出来。有的小朋友要站起来高喊了,“怎么写不出来,你瞎说,我来写”,一顿操作写出了下面的代码:


// 小朋友写的错误代码


flow<Editable> {


editText.doAfterTextChanged { text ->


emit(text) // 这里是错误的,emit 不可以写在内部类中


}


}.debounce(500)


.collect {


println("----------------->>> $it")


}


错误的地方我写上了注释,emit 是一个 suspend 挂起函数,是不可以写在内部类里的,代码直接编译不通过。


真正的正确写法


=======


首先我提一个知识点,大家回忆一下。RxJava 中的流,是分为冷流热流(即:cold Observable 和 hot Observable)对吧。如果你说啥,流还分冷热?亲,那这里建议你炒个回锅肉呢。


在 RxJava 的使用中,不注意区分冷热流,是导致 RxJava 错用、滥用的原因之一!


这里我只用两句话简单解释冷热流,不展开讲 RxJava。


  • 冷流:只有观察者进行订阅了,上游才开始执行发射数据

  • 热流:无论有没有观察者,上游的数据都会发射


flow 是冷流


=======


直接用注释说明:


flow {


// 发射数据


}.collect {


/*


只有执行了 collect 或者 collectLast 订阅了流,


上游 flow 里面的代码块才会执行!

评论

发布
暂无评论
「正确」的使用Kotlin Flow进行搜索优化