[正确]的使用Kotlin Flow进行搜索优化

防抖(debounce) 和 节流(throttling) 防抖和节流是针对响应跟不上触发频率这类问题的两种解决方案。 在给DOM绑定事件时,有些事件我们是无法控制触发频率的。 如鼠标移动事件onmousemove, 滚动滚动条事件onscroll,窗口大小改变事件onresize,瞬间的操作都会导致这些事件会被高频触发。 如果事件的回调函数较为复杂,就会导致响应跟不上触发,出现页面卡顿,假死现象。 在实时检查输入时,如果我们绑定onkeyup事件发请求去... 阅读详情

引言

用户搜索时,为了避免产生无意义的搜索请求,通常会进行搜索数据限流。熟悉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) // 这里是有效的 限流
 .collect {
      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 里面的代码块才会执行!
    */
}
复制代码

现在这位小朋友,冷静一下,想想输入框的业务场景是什么样子的?即:不管有没有订阅者,只要EditText文本变化了,都会发送数据。那我们就应该用热流来解决问题。

StateFlow热流登场

各位大佬直接看代码吧:

// 定义一个全局的 StateFlow
private val _etState = MutableStateFlow("")

override fun onCreate(savedInstanceState: Bundle?) {
    et.doAfterTextChanged { text ->
        // 往流里写数据
        _etState.value = (text ?: "").toString()
    }

    lifecycleScope.launch {
        _etState
        .sample(500) // 限流,500毫秒
        .filter {
            // 空文本过滤掉
            it.isNotBlank()
        }.collect {
            // 订阅数据
            println("----------------->>> $it")
        }
    }
}

复制代码

好了,收工了。对于 StateFlow ,Google是这么解释的:“与使用 flow 构建器构建的冷数据流不同,StateFlow 是热数据流:从数据流收集数据不会触发任何提供方代码。StateFlow 始终处于活跃状态并存于内存中,而且只有在垃圾回收根中未涉及对它的其他引用时,它才符合垃圾回收条件。”

文档链接:StateFlow 和 SharedFlow

课后作业

最后的代码中,我是用了sample()方法来作为限流,而没有使用debounce()方法限流。那么这两种限流的方法有什么区别呢?有兴趣的同学自己在代码里尝试一下吧,会得出自己的结论的。

(对于此场景,我更倾向于sample()方法限流)。

[正确]的使用Kotlin Flow进行搜索优化,kotlin面试题 还不懂的话,那就看下面简化的代码: // 文章错误代码????的简化 for (i in 0..100) { // 模拟生成数据 flow<Int> { emit(i) }.debounce(500) // 这里是无效的 限流,因为 flow 的 emit 只执行了一次啊…… .collect { println("----------------->>> $it") } } 阅读详情

相关推荐

Windows安装ros2(Jazzy版本+win10/win11)-4.构建ros2结点

这个位置也是ros2搜索package以及搜索node的路径, 如果把构建好的可执行文件乱动位置的话就找不到节点了,当然如果复制一个可执行文件以及可执行文件-script.py文件, ros2也就会认为你有一个新的节点了,运行这个拷贝的可执行文件程序都是ok的。由于上一个文章给powershell7也增加了启动执行ros2的环境初始化文件local_setup.ps1, 所以我们也可以直接在vscode中运行节点, 此种方式没有经由ros2托管, 缺少其他ros2的附加能力。

weixin_48398592的博客 7113

Kotlin协程flow发送时间间隔debounce

debounce蕴含了一定的缓冲思想,即,不立刻触发事件,而是先把要发射的数据进入队列,稍等一定时间(时间)延迟触发,而触发的重要条件取决于前一条数据和后一条数据的时间间隔,注意,前一条和后一条尚未被发射出去,只是待命中。发射完ABC,Kotlin审视待发射的ABCD,按理说ABCD与ABC间隔200,满足发射timeOut值,但是ABCD与ABCDE间隔100,所以跳过ABCD,直接发射ABCDE。四、map,重组改写数据。A和AB都待发射,A和AB间隔100,所以跳过A,直接发射AB。

Zhang Phil 2430

如何从零开始写小程序

看了这篇文章,即使让我现在就从头写一个能够正常运行的小程序,也没有原本想象中的那么难了。 在本文中,我们将会以一个具体的小程序为例,带领大家从零到一完成一个小程序的开发流程,并将这个小程序上传到 FinClip.com 进行小程序提审与上架操作。 我们新建了一个叫做「HelloWorld」的小程序,FIDE 在初始化小程序项目时,会自动在项目目录中补充对应所需要的项目文件。那不妨让我们先从小程序目录下的配置文件开始,逐渐揭开小程序的面纱。 使用 FIDE 编辑小程序 1. 认识 json 文件 在小程序项目

POHOU23的博客 4395

Kotlin协程flow的debounce与管道Channel

kotlin协程管道Channel。debounce蕴含了一定的缓冲思想,即,不立刻触发事件,而是先把要发射的数据进入队列,稍等一定时间(时间)延迟触发,而触发的重要条件取决于前一条数据和后一条数据的时间间隔,注意,前一条和后一条尚未被发射出去,只是待命中。发射完ABC,Kotlin审视待发射的ABCD,按理说ABCD与ABC间隔200,满足发射timeOut值,但是ABCD与ABCDE间隔100,所以跳过ABCD,直接发射ABCDE。A和AB都待发射,A和AB间隔100,所以跳过A,直接发射AB。

Zhang Phil 792

避坑指南:Windows11语言包安装后部分界面仍显示中文的终极解决方案

本文详细解析了Windows11语言包安装后部分界面仍显示中文的问题,提供了从基础到进阶的完整解决方案。通过PowerShell命令、注册表清理和系统文件检查等方法,帮助用户彻底解决语言显示不一致的问题,确保系统界面语言统一。

weixin_29232507的博客 1633

手把手教你用GD32F407VET6的EXMC驱动外部SRAM,搞定大内存需求

本文详细介绍了如何使用GD32F407VET6的EXMC外设驱动外部SRAM,解决嵌入式开发中的大内存需求问题。通过硬件连接方案、EXMC时序配置与初始化步骤,以及软件集成与内存管理技巧,帮助开发者快速实现内存扩展。特别适合需要处理图形显示缓冲、音频处理等大内存场景的GD32F407开发者。

weixin_30752699的博客 346

Kotlin Flow中的3个数据相关的操作符:debounce、buffer和conflate

debounce操作符用于过滤频繁发射的数据项,只保留最后一个在指定时间内发射的数据项。常用于处理用户输入、按钮点击等可能频繁触发的事件,避免不必要的操作频繁发生。bufferbuffer和conflate都是用于处理流的性能优化操作符。buffer通过引入缓存区降低背压,让上下游可以并发运行。conflate则直接跳过中间值,只保留最新的,大幅度减少处理频率,适用于对最新数据更敏感的场景。

chuyouyinghe的专栏 723

unity 腾讯地图sdk移动和缩放代码

unity 腾讯地图sdk 实现移动端 缩放 和 移动

。。。。。 1283

【Kotlin】Flow 中的三个数据相关的操作符:debounce、buffer 和 conflate

在 Kotlin 中,Flow 是一种处理异步数据流的 API,它类似于 RxJava 中的 Observable。

Creativity + Efficiency = Success 1127

高性能算力中心 — RDMA — Overview

目录 文章目录目录RDMA基于以太网的 RoCE/RDMA 计算优化NVMeNVMe Over Fabrics基于以太网的 NVMe 存储优化 RDMA RDMA(Remote DMA,远程直接内存访问)是一种新的内存访问技术,RDMA 让计算机可以直接存取其他计算机的内存,而不需要经过 CPU 耗时的处理。RDMA 将数据从一个系统快速移动到远程系统存储器中,而不对操作系统造成任何影响。RDMA 技术的原理及其与 TCP/IP 架构的对比如下图所示。 InfiniBand(IB):从一开始就支持 R

烟云的计算 2365

无人机威胁检测(Hostile Drone Detection)——基于YOLOv10与UI界面的实现

Anti-UAV数据集由多种场景下的无人机视频与图片组成,包含无人机目标的多样化姿态、背景、光照变化,专门用于反无人机检测研究。YOLO(You Only Look Once)系列是当前流行的实时目标检测算法,具有速度快、精度高的特点。网络结构优化:更深更轻的主干网络,提升特征提取能力。检测头改进:多尺度特征融合,更好检测小型目标如无人机。训练技巧:使用自动混合精度训练(AMP)、数据增强、标签平滑等技术。

YOLO 229

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

引言 用户搜索时,为了避免产生无意义的搜索请求,通常会进行搜索数据限流。熟悉RxJava的同学,一定会知道怎么做,各种天花乱坠的操作符让你眼花缭乱。 那么用上了kotlin的小伙伴,完全可以不必使用RxJava,因为kotlin中自带的Flow就可以做到。不废话,直接开始。 激起我写作的原因是这一篇文章Kotlin Flow 开发应用实践之搜索优化,这篇文章错误的使用了Flow,目前作者已经对文章内部的错误进行了更改,但是我还是想借机来说明一下。随后给出正确的解释及正确的代码。 错在了哪 我先把那

Androidbye的博客 700

ECU诊断功能测试:从理论到实践

ECU诊断功能是指通过特定的诊断协议与ECU进行通信,以获取ECU的状态信息、故障码、数据流等,并执行特定的诊断操作。诊断功能的主要目的是帮助开发人员和维修人员快速定位和解决ECU中的问题,确保车辆的安全性和可靠性。UDS协议是ISO 14229标准的一部分,定义了一系列的诊断服务,如读取故障码、清除故障码、读取数据流等。UDS协议基于CAN(Controller Area Network)总线,具有较高的灵活性和扩展性。读取故障码是诊断功能中最基本的操作之一。通过读取故障码,可以快速定位ECU中的问题。

闲人编程的博客 1806

「正确」的使用Kotlin Flow进行搜索优化,androidsdk开发文档

错在了哪 ==== 我先把那篇文章中错误的代码贴上来: // 错误代码 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) }

m0_66264699的博客 290

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

[正确]的使用Kotlin Flow进行搜索优化,flutter二维码扫描插件

错在了哪 我先把那篇文章中错误的代码贴上来: // 错误代码???? 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) }

m0_66264881的博客 341

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

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

我最近从朋友那里收集到了2020-2021BAT 面试真题解析Android 基础、Java 基础、Android 源码相关分析、常见的一些原理性问题等等,可以很好地帮助大家深刻理解Android相关知识点的原理以及面试相关知识。这份资料把大厂面试中常被问到的技术点整理成了PDF,包知识脉络 + 诸多细节;还有 高级架构技术进阶脑图 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。这里也分享给广大面试同胞们,希望每位程序猿们都能面试成功~点击直达GitHub。

m0_60388292的博客 1123

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

「正确」的使用Kotlin Flow进行搜索优化,最新Android笔试题分享

binding.tvShow.text = it.toString() }.flowOn(Dispatchers.Main) .launchIn(lifecycleScope) } 仔细看上面的代码,你们自己想想错在了哪里? 文本输入框etSearch每次文本的变化都会回掉searchFilter()方法,而方法里面每次都去实例化了一个flow,然后又使用了debounce()限流,那么这个debounce()限流的意义何在?毫无意义啊,对吧。因为每次都是新创建的flow啊。 还不懂的话,那就看下面简化的代

wq221aas的博客 241

Kotin Flow 防抖操作符详解(debounce)

文章摘要 防抖(Debounce) 是一种限制数据流频率的操作符,其核心逻辑是:仅在输入值停止出现一段指定时间后,才将最新值传递到下游。它适用于高频触发场景(如用户输入、滚动事件),避免频繁调用下游逻辑。 Kotlin Flow 提供了 debounce 操作符,支持固定超时、基于 Duration 的动态超时,以及根据输入值调整等待时长。例如: 固定超时:debounce(1000) 等待 1 秒静默后发送最新值。 动态超时:通过 Lambda 按输入值类型(如优先级)调整等待时间。 典型应用包括 搜索框

移动端开发干货分享 1466

Kotlin_Flow_完整使用指南

Flow 是 Kotlin 协程库中的冷流(Cold Stream),用于异步返回多个值的序列。// 创建一个简单的 Flowemit(1)delay(100)emit(2)delay(100)emit(3)// 收集 Flowprintln(value) // 输出: 1, 2, 3emit(value) // 发射原值emit(value * 10) // 再发射一个转换值需求使用的操作符简单值转换map流的转换过滤值filter防抖搜索debounce组合多个流combine。

qq_53374893的博客 1350

如何本地跑起 PDFMathTranslate:AI PDF 翻译保留公式版式的完整指南

PDFMathTranslate(命令名叫 pdf2zh)是一款做本地 PDF 翻译的 AI 工具:把外文科学论文翻成中文,公式、图表、目录和注释的位置原封不动,支持图形界面、Docker 容器和命令行三种启动方式。这篇文章带你从零装好并跑起来。 [![PDFMathTranslate AI PDF 翻译实时预览动图](https://raw.gitcode.com/GitHub_Trendin

gitblog_00745的博客 930

Kotlin Flow Marbles 教程

Kotlin Flow Marbles 教程 项目介绍 Kotlin Flow Marbles 是一个专注于视觉化展示 Kotlin Flow 工作流的开源项目。它通过交互式的图表帮助开发者更好地理解Flow的各种操作符以及它们在数据流处理中的行为。此项目对于学习Kotlin的响应式编程至关重要,特别是对于那些希望通过可视化方式来加深对Kotlin Flow概念理解的开发人员来说。 项目快速启动 ...

gitblog_00877的博客 986

面试心得体会1000字,「正确」的使用Kotlin Flow进行搜索优,2024年Android工作或许更难找

/ 错误代码.filter {.onEach {LogUtils.d(“输出:$it”)仔细看上面的代码,你们自己想想错在了哪里?文本输入框etSearch每次文本的变化都会回掉searchFilter()方法,而方法里面每次都去实例化了一个flow,然后又使用了debounce()限流,那么这个debounce()限流的意义何在?毫无意义啊,对吧。因为每次都是新创建的flow啊。// 文章错误代码的简化// 模拟生成数据flow {emit(i)

1024

Kotlin中Flow

A协程集成深度Flow 是 Kotlin 协程原生组件,支持结构化并发LiveData 是 Android 生命周期感知组件RxJava 是独立响应式扩展库背压处理能力Flow 内置多种背压策略(bufferconflateLiveData 无背压概念(仅最新值)RxJava 需手动配置背压策略流控制能力LiveData 仅支持简单值观察RxJava 操作符更丰富但学习曲线陡峭Android 集成Flow 需要实现生命周期感知LiveData 自动处理生命周期RxJava 需额外绑定生命周期Q。

qq_45906596的博客 1365

Kotlin-Flow-Android-Examples 项目推荐

Kotlin-Flow-Android-Examples 是一个专注于使用 Kotlin Flow 进行 Android 开发的示例项目。该项目由 MindorksOpenSource 团队维护,主要使用 Kotlin 编程语言。Kotlin Flow 是 Kotlin 协程的一部分,用于处理异步数据流,特别适用于 Android 应用中的数据流处理。 ## 项目核心功能 该项目的核心功能是通...

gitblog_00375的博客 628

Kotlin Flow 全面解析与实战

Kotlin Flow是协程库中处理异步数据流的核心组件,支持顺序发射多个值。它具有冷流特性(按需执行)、顺序性和异步性。文章详细解析了Flow的创建方式、操作符(过渡/终端/异常处理)、上下文切换和高级特性(多流组合/背压处理)。对比了冷流与热流(StateFlow/SharedFlow)的特点与适用场景,并给出Android开发中的实际应用方案,包括生命周期感知收集、网络数据库结合和搜索功能实现。最后介绍了调试测试方法和性能优化建议,帮助开发者全面掌握这一异步数据流处理工具。

油墨香^-^的博客 915
上一篇: 37岁Android程序员被裁员,面试大厂被拒,降薪去小公司,心更凉了
下一篇: 阿里35岁Android程序员晋升无望,该何去何从,在线等网友给点建议
紫苏不是菜
博客等级 码龄6年 40粉丝 32原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值