【Kotlin学习】协程的基本概念(3)——Flow

kotlin flow介绍

它是kotlin协程与响应式编程模型结合的产物

flow的使用

flow的基本使用方式

flow能够返回多个异步计算的值

在这里插入图片描述

如果熟悉RxJava,可以吧collect()对应subscribe(),而emit()对应onNext()

另外的创建flow方式
1.flowOf()

在这里插入图片描述

2.asFlow()

在这里插入图片描述

3.channelFlow()

在这里插入图片描述

channelFlow builderflow builder是有一定差异的
1.flow是Cold Stream,在没有切换线程的情况下,生产者和消费者是同步非阻塞
2.channel Flow是Hot Stream,channelFlow实现了生产者和消费者异步非阻塞模型

使用flow builder,大致花费1s

在这里插入图片描述

在这里插入图片描述

使用channelFlow builder

在这里插入图片描述

在这里插入图片描述

如果flow切换线程的化花费的时间会跟使用channelFlow builder的效果差不多

切换线程

只需要使用flowOn就可以切换线程

在这里插入图片描述

在这里插入图片描述

collect()指定哪个线程,要看整个flow处于哪个CoroutineScope

!不要用withContext切换flow线程

取消flow

如果flow是在一个挂起函数内被挂起了,那么flow是可以被取消的,否则不能

终端操作符

flow的API类似于java stream的API,它同样拥有Intermediate、Opreations、TerminalOperations

flow的Terminal运算符可以是suspend函数,如collect、single、reduce等,也可以是launchIn运算符,用于在指定CoroutineScope内使用flow

Terminal运算符

1.collect
2.single/first
3.toList/toSet/toCollection
4.count
5.fold/reduce
6.launchIn/produceIn/broadcastIn

flow的生命周期

flow有onStartonCompletion来监听flow的创建和结束

在这里插入图片描述

在这里插入图片描述

在Android中使用flow创建网络请求时通过onStart操作符调用loading动画以及网络请求结束后通过onCompletion操作符取消动画,或者做一些日志的打印

flow和RxJava

flow和sequences

每一个flow其内部都是按照顺序执行的,这一点和Sequenece类似。但是flow不会阻塞主线程的运行,而sequence会阻塞主线程的运行

使用flow

在这里插入图片描述

在这里插入图片描述

使用sequence

在这里插入图片描述

在这里插入图片描述

flow和RxJava

kotlin协程库参考了RxJava

RxJava2/3Flow
SingleDefered
MaybeDefered
CompletableJob
ObservableChannel、Flow
FlowableChannel、Flow

1.Cold Stream

flow的代码块只有调用collected()才开始运行,正如RxJava创建的Observables只有调用subscribe()才开始运行一样

2.HotStream

可以借助Kotlin Channel来实现Hot Stream

3.Completion

flow完成(正常或出现异常)时,若需要执行一个操作,可以通过imperativedeclarative来完成

imperative

通过使用try…finally实现

在这里插入图片描述

declarative
通过onCompletion()函数实现

在这里插入图片描述

onCompleted(借助扩展函数实现)

在这里插入图片描述

但当flow异常结束时不会执行onCompleted()

4.Backpressure

它是响应式编程会遇到的问题之一

RxJavaFlowable支持的Backpressure策略包括

1.MISSING

创建的Flowable没有指定背压策略,不会对通过onNext发射的数据做缓存或丢弃处理

2.ERROR

如果放入Flowable的异步缓存池的数据超限了,就会抛出MissingBackpressureException异常

3.BUFFER

Flowable的异步缓存池和Observable的一样,没有固定大小,可以无限制添加数据,不会抛出MissingBackpressureException,但会导致OOM

4.DROP

如果Flowable的异步缓存池满了,就会丢掉将要放入缓存池中的数据

5.LATEST

如果缓存池满了,就会丢掉将要放入缓存池中的数据,这一点和DROP策略一样,不同的是,无论缓存池的状态如何,LATEST策略都会将最后一条数据强行放入缓存池中

flow支持的Backpressure通过挂起函数实现

buffer()对应BUFFER策略

在这里插入图片描述

在这里插入图片描述

conflate对应LATEST策略

在这里插入图片描述
在这里插入图片描述

flow的异常处理

flow可以用try…catch来捕捉异常

catch操作符

前面讲过onCompletion操作符,但onCompletion不能捕获异常,只能用于判断是否有异常。catch操作符可以捕获来自上游的异常

在这里插入图片描述
在这里插入图片描述

若把onCompletion、catch交换位置,当catch操作符捕获到异常后,不会影响下游

在这里插入图片描述
在这里插入图片描述

catch操作符用于实现异常透明化处理,在catch操作符内可以使用throw再次抛出异常,可以使用emit()转换为发射值还可用于其他业务。但catch只是中间操作符,不能捕获下游的异常,但我们可以多次使用catch,还可以借助onEach,把业务逻辑放到onEach中,在onEach之后时catch,再之后是collect

retryretryWhen操作符

如果上游遇到异常并使用了retry操作符,那么retry会让flow最多重试retries指定的次数

在这里插入图片描述

在这里插入图片描述
retry操作符最终调用的是retryWhen操作符

在这里插入图片描述

retryWhen操作符的参数是谓词,当谓词返回true时才会进行重试,谓词还接收一个attempt作为参数,表示尝试的次数,从0开始

flow的线程操作

flowOn和RxJava的observeOn

obServeOn操作符接收一个Scheduler参数,用来指定下游操作符运行在特定的线程调度器Scheduler上。flowOn操作符接收一个CoroutineContext参数,影响的是上游的操作

在这里插入图片描述
在这里插入图片描述

flow builder和map都会受到flowOn影响,并使用Dispatchers.io线程池
在这里插入图片描述在这里插入图片描述

flow builder和两个map操作符都会受到两个flowOn的影响,第二个map操作符会切换到指定的线程池

buffer实现并发操作

buffer操作符也可以并发地执行任务,它是除了使用flowOn操作符之外的另一种方式,只是不能显式指定Dispatchers

在这里插入图片描述
在这里插入图片描述

删除buffer后
在这里插入图片描述

并行操作

并发与并行的区别

1.并发:一个处理器同时处理多个任务
2.并行:多个处理器或者多核处理器同时处理多个不同的任务,并行是同时发生的多个并发时间

在flow中可以使用flatMapMerge实现并行

在这里插入图片描述

输出的数字为乱序

flow的其他操作符

转换操作符transform

在使用它时可以任意多次调用emit,这时它和map的最大区别

在这里插入图片描述

在这里插入图片描述

限制大小的操作符take

只取前几个emit发射的值

在这里插入图片描述在这里插入图片描述

终端操作符

reduce

类似于kotlin集合的reduce函数,能够对集合进行计算操作

对平方数列求和

在这里插入图片描述

fold

也类似于kotlin集合的fold函数,也需要设置初始值

对平方数列求和

在这里插入图片描述

reduce和fold

在这里插入图片描述
在这里插入图片描述

查看两者源码我们可以看到,reduce把第一个元素当作起始值,而fold把我们自己设定的值作为初始值

合并操作符

zip

它可以将两个flow进行合并

在这里插入图片描述
在这里插入图片描述

它会把flowa中的一个item和flowb中对应的一个item进行合并,即使flowb中的每一个item都使用了delay(),在合并过程中也会等待delay()执行完再进行合并。若a中item个数大于b中个数,新的flow的item个数等于较小的flow的item个数

combine

每次从a发出新的item会将其与folwb最新的item合并

在这里插入图片描述
在这里插入图片描述

flattenMerge

它不会组合多个flow,而是把它们作为单个流执行

在这里插入图片描述
在这里插入图片描述在这里插入图片描述

扁平化操作符

flatMapConcat

它由mapflattenConcat操作符实现
在这里插入图片描述

在调用它之后,collect函数在收集新值之前会等待flatMapConcat内部的flow完成

在这里插入图片描述
在这里插入图片描述

flatMapMerge

在这里插入图片描述

它顺序调用内部代码块并且并行地执行collect函数

在这里插入图片描述
在这里插入图片描述

flatMapLatest

当发射了新值之后,上个flow就会被取消

在这里插入图片描述在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值