总共计划是用三篇文章讲完,而本篇则是这个系列的第二篇文章。如果你还没有看过前面的基础知识入门的话,可以先去参考这里 Kotlin Flow响应式编程,基础知识入门 。
本篇文章我打算着重讲解一下操作符函数的相关内容。什么是操作符函数果你熟悉RxJava,那么对于操作符函数一定不会陌生。如果你不熟悉RxJava,那么操作符函数就是那个让RxJava如此难学的元凶。
准确来说,RxJava的操作符函数不是难,而是多。之前Google在刚推出自家LiveData时也曾调侃过,我们的操作符函数只有两个,可不像某些库有上百万个那么多。
我相信应该没有任何一个人能够熟练掌握RxJava的所有操作符函数,这一点越是RxJava的老手应该越是深有体会。正确的做法是,只去熟记那些最常用的操作符函数即可,剩下绝大多数的操作符函数都是不太能用得到的,或者需要用到时再去查阅文档学习即可。
那么Kotlin Flow的操作符函数也是类似的,虽然它没有RxJava那么多,但是着实也不少。本篇文章我会尽可能将最常用的操作符函数全部覆盖到,那么学完本篇文章之后,在绝大部分Kotlin Flow的操作符函数使用场景中,你应该都可以比较得心应手了。
另外,我对接下来即将介绍的所有操作符函数按照功能相似度以及难易程度进行了分组,会按照先易后难的原则一一进行介绍。
话不多说,开始走起。
0. setup
我们会以全程实践的方式来学习文中所有的操作符函数。因此,将实践环境提前搭建好是必不可少的。
首先创建一个Android项目,并在项目中添加如下依赖库:
由于Flow以及操作符函数并不依赖于Android项目,因此我们并不必非得在Android项目中来进行实践。简单起见,我们只需要在一个Kotlin类当中来实践本篇文章的内容即可。
创建一个Flow.kt类,并在其中定义一个main()函数,如下所示:
这里我们在main()函数中添加了一个runBlocking代码块,它的作用是提供协程作用域给稍后的Flow使用,并且在代码块中的所有代码执行完之前阻塞当前线程。
因此,我们把后续的所有例子都放到runBlocking代码块中去执行就可以了。
另外当你定义好了main()函数之后,你会发现它的左边会出现一个运行箭头:
这就是map操作符函数,非常简单,相信你一下子就已经理解了。
2. filter
filter也是一个非常简单的操作符函数。顾名思义,它是用来过滤掉一些数据的。
Flow当中的操作符函数既可以单独使用,也可以结合其他操作符函数一起使用。
这里我们通过结合filter和map这两个操作符函数,来快速演示一下用法,你就立刻能掌握了。
这里在filter函数中指定了一个条件,判断数据是否是偶数。
因而,flow中的数据只有是偶数的情况下才会继续向下传递,奇数则会被filter函数过滤掉。
验证一下结果,如下图所示:
没有问题,结果正如我们想象的那样,所有偶数都被打印出来了。
4. debounce
最简单的操作符函数差不多就这些,接下来要学习稍微有些难度的操作符函数了。
debounce函数可以用来确保flow的各项数据之间存在一定的时间间隔,如果是时间点过于临近的数据只会保留最后一条。
这个函数在某些特定场景下特别有用。
想象一下我们正在Edge浏览器的地址栏中输入搜索关键字,浏览器的地址栏下方通常都会给出一些搜索建议。
这里使用emit()函数依次发送了1、2、3、4、5这几条数据。其中,1和2是连续发送的,2和3之间存在600毫秒的间隔,因此2可以发送成功。3和4之间、4和5之间间隔只有100毫秒,因此都无法发送成功。5由于是最后一条数据,因此可以发送成功。
那么打印结果应该是2和5:
可以看到,虽然弹幕的发送量无限大,但是我们每秒钟只会打印出一条弹幕,这就是sample操作符函数的用法了。
6. reduce
刚才学习的几个操作符函数最终都还是要通过collect函数来收集结果的。
接下来我们学习两个不需要借助collect函数,自己就能终结整个flow流程的操作符函数,这种操作符函数也被称为终端操作符函数。
首先来看reduce函数。我个人认为reduce函数还是比较好理解的,它的基本公式如下:
其中acc是累积值的意思,value则是当前值的意思。
也就是说,reduce函数会通过参数给我们一个Flow的累积值和一个Flow的当前值,我们可以在函数体中对它们进行一定的运算,运算的结果会作为下一个累积值继续传递到reduce函数当中。
举一个更加具体点的例子,我们上学时学等差数列都会讲这个故事,高斯的老师让全班同学计算从1加到100的结果。
今天我们不需要借助等差数列,只需要借助reduce函数就可以立刻算出结果了:
这里需要注意的是,reduce函数是一个终端操作符函数,它的后面不可以再接其他操作符函数了,而是只能获取最终的运行结果。
那么运算结果毫无疑问是5050:

7. fold
fold函数和reduce函数基本上是完全类似的,它也是一个终端操作符函数。
主要的区别在于,fold函数需要传入一个初始值,这个初始值会作为首个累积值被传递到fold的函数体当中,它的基本公式如下:
总体区别就这么多,所以我感觉fold函数并没有什么好讲的,它和reduce函数具体用谁只取决于你编程时的业务逻辑需求。
但是其实reduce函数和fold函数并不是只能用作数值计算,相反它们可以作用于任何类型的数据。因此,这里我就用fold函数来演示一个字符串拼接的功能吧:
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!