当前位置:   article > 正文

10 个有用的 Kotlin flow 操作符

kotlin flow 操作符

Kotlin 拥有函数式编程的能力,运用得当,可以简化代码,层次清晰,利于阅读,用过都说好。

然而操作符数量众多,根据使用场景选择合适的操作符是一个很大的难题,网上搜索了许久只是学习了一个操作符,还要再去验证它,实在浪费时间,开发效率低下。

一种方式是转至命令式开发,将过程按步骤实现,即可完成需求;另一种方式便是一次学习多个操作符,在下次选择操作符时,增加更多选择。

本篇文章当然关注的是后者,列举一些比较常用 Kotlin 操作符,为提高效率助力,文中有图有代码有讲解,文末有参考资料和一个交互式学习的网站。

让我们开始吧。

1. reduce

reduce 操作符可以将所有数据累加(加减乘除)得到一个结果

listOf(1, 2, 3).reduce { a, b ->
    a + b
}

输出:6
  • 1
  • 2
  • 3
  • 4
  • 5

如果 flow 中没有数据,将抛出异常。如不希望抛异常,可使用 reduceOrNull 方法。

reduce 操作符不能变换数据类型。比如,Int 集合的结果不能转换成 String 结果。

2. fold

fold 和 reduce 很类似,但是 fold 可以变换数据类型

有时候,我们不需要一个结果值,而是需要继续操 flow,可使用 runningFold 。

flowOf(1, 2, 3).runningFold("a") { a, b ->
    a + b
}.collect {
    println(it)
}

输出:
a
a1
a12
a123
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

同样的,reduce 也有类似的方法 runningReduce

flowOf(1, 2, 3).runningReduce { a, b ->
    a + b
}.collect {
    println(it)
}

输出:
1
3
6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

3. debounce

debounce 需要传递一个毫秒值参数,功能是:只有达到指定时间后才发出数据,最后一个数据一定会发出

例如,定义 1000 毫秒,也就是 1 秒,被观察者发出数据,1秒后,观察者收到数据,如果 1 秒内多次发出数据,则重置计算时间。

flow {
    emit(1)
    delay(590)
    emit(2)
    delay(590)
    emit(3)
    delay(1010)
    emit(4)
    delay(1010)
}.debounce(
    1000
).collect {
    println(it)
}

输出结果:
3
4
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

rebounce 的应用场景是限流功能

4. sample

sample 和 debounce 很像,功能是:在规定时间内,只发送一个数据

flow {
    repeat(4) {
        emit(it)
        delay(50)
    }
}.sample(100).collect {
    println(it)
}

输出结果:
1
3
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

sample 的应用场景是截流功能

debounce 和 sample 的限流和截流功能已有网友实现,点击这里

5. flatmapMerge

简单的说就是获得两个 flow 的乘积或全排列,合并并且平铺,发出一个 flow。

描述的仍然不好理解,一看代码便能理解了

flowOf(1, 3).flatMapMerge {
    flowOf("$it a", "$it b")
}.collect {
    println(it)
}

输出结果:
1 a
1 b
3 a
3 b
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

flatmapMerge 还有一个特性,在下一个操作符里提及。

6. flatmapConcat

先看代码。

flowOf(1, 3).flatMapConcat {
    flowOf("a", "b", "c")
}.collect {
    println(it)
}
  • 1
  • 2
  • 3
  • 4
  • 5

功能和 flatmapMerge 一致,不同的是 flatmapMerge 可以设置并发量,可以理解为 flatmapMerge 是线程安全的,而 flatmapConcat 不是线程安全的。

本质上,在 flatmapMerge 的并发参数设置为 1 时,和 flatmapConcat 基本一致,而并发参数大于 1 时,采用 channel 的方式发出数据,具体内容请参阅源码。

7. buffer

介绍 buffer 的时候,先要看这样一段代码。

flowOf("A", "B", "C", "D")
.onEach {
    println("1 $it")
}
.collect { println("2 $it") }

输出结果:
1 A
2 A
1 B
2 B
1 C
2 C
1 D
2 D
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

注意输出的内容。

加上 buffer 的代码。

flowOf("A", "B", "C", "D")
.onEach {
    println("1 $it")
}
.buffer()
.collect { println("2 $it") }

输出结果:
1 A
1 B
1 C
1 D
2 A
2 B
2 C
2 D
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

输出内容有所不同,buffer 操作符可以改变收发顺序,像有一个容器作为缓冲似的,在容器满了或结束时,下游开始接到数据,onEach 添加延迟,效果更明显。

8. combine

合并两个 flow,长的一方会持续接受到短的一方的最后一个数据,直到结束

[图片上传失败…(image-9f101a-1664178384778)]

flowOf(1, 3).combine(
    flowOf("a", "b", "c")
) { a, b -> b + a }
.collect {
    println(it)
}

输出结果:
a1
b3
c3
复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

9. zip

也是合并两个 flow,结果长度与短的 flow 一致,很像木桶原理。

flowOf(1, 3).zip(
    flowOf("a", "b", "c")
) { a, b -> b + a }
.collect {
    println(it)
}

输出结果:
a1
b3
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

10. distinctUntilChanged

就像方法名写的那样,和前一个数据不同,才能收到,和前一个数据想通,会被过滤掉。

flowOf(1, 1, 2, 2, 3, 1).distinctUntilChanged().collect {
    println(it)
}

输出结果:
1
2
3
1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

最后

以上就是今天要介绍的操作符,希望对大家有所帮助。

参考文章:Android — 9 Useful Kotlin Flow Operators You Need to Know

Kotlin 交互式操作符网站:交互式操作符网站

作者:亢龙有悔
链接:https://juejin.cn/post/7135013334059122719

文末福利

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
在这里插入图片描述
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

一、架构师筑基必备技能

1、深入理解Java泛型
2、注解深入浅出
3、并发编程
4、数据传输与序列化
5、Java虚拟机原理
6、高效IO
……

在这里插入图片描述

二、Android百大框架源码解析

1.Retrofit 2.0源码解析
2.Okhttp3源码解析
3.ButterKnife源码解析
4.MPAndroidChart 源码解析
5.Glide源码解析
6.Leakcanary 源码解析
7.Universal-lmage-Loader源码解析
8.EventBus 3.0源码解析
9.zxing源码分析
10.Picasso源码解析
11.LottieAndroid使用详解及源码解析
12.Fresco 源码分析——图片加载流程

在这里插入图片描述

三、Android性能优化实战解析

  • 腾讯Bugly:对字符串匹配算法的一点理解
  • 爱奇艺:安卓APP崩溃捕获方案——xCrash
  • 字节跳动:深入理解Gradle框架之一:Plugin, Extension, buildSrc
  • 百度APP技术:Android H5首屏优化实践
  • 支付宝客户端架构解析:Android 客户端启动速度优化之「垃圾回收」
  • 携程:从智行 Android 项目看组件化架构实践
  • 网易新闻构建优化:如何让你的构建速度“势如闪电”?

在这里插入图片描述

四、高级kotlin强化实战

1、Kotlin入门教程
2、Kotlin 实战避坑指南
3、项目实战《Kotlin Jetpack 实战》

  • 从一个膜拜大神的 Demo 开始

  • Kotlin 写 Gradle 脚本是一种什么体验?

  • Kotlin 编程的三重境界

  • Kotlin 高阶函数

  • Kotlin 泛型

  • Kotlin 扩展

  • Kotlin 委托

  • 协程“不为人知”的调试技巧

  • 图解协程:suspend

在这里插入图片描述

五、Android高级UI开源框架进阶解密

1.SmartRefreshLayout的使用
2.Android之PullToRefresh控件源码解析
3.Android-PullToRefresh下拉刷新库基本用法
4.LoadSir-高效易用的加载反馈页管理框架
5.Android通用LoadingView加载框架详解
6.MPAndroidChart实现LineChart(折线图)
7.hellocharts-android使用指南
8.SmartTable使用指南
9.开源项目android-uitableview介绍
10.ExcelPanel 使用指南
11.Android开源项目SlidingMenu深切解析
12.MaterialDrawer使用指南
在这里插入图片描述

六、NDK模块开发

1、NDK 模块开发
2、JNI 模块
3、Native 开发工具
4、Linux 编程
5、底层图片处理
6、音视频开发
7、机器学习

在这里插入图片描述

七、Flutter技术进阶

1、Flutter跨平台开发概述
2、Windows中Flutter开发环境搭建
3、编写你的第一个Flutter APP
4、Flutter开发环境搭建和调试
5、Dart语法篇之基础语法(一)
6、Dart语法篇之集合的使用与源码解析(二)
7、Dart语法篇之集合操作符函数与源码分析(三)

在这里插入图片描述

八、微信小程序开发

1、小程序概述及入门
2、小程序UI开发
3、API操作
4、购物商场项目实战……

在这里插入图片描述

全套视频资料:

一、面试合集
在这里插入图片描述
二、源码解析合集

在这里插入图片描述
三、开源框架合集

在这里插入图片描述
欢迎大家一键三连支持,若需要文中资料,直接点击文末CSDN官方认证卡片免费领取↓↓↓

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/575994
推荐阅读
相关标签
  

闽ICP备14008679号