在之前的Flow,collect函数浅析和仿Flow构建器创建数据流文章中我们探索了flow的简单使用及它的简单原理,但是生产过程中我们往往会借用这些基础的api实现我们复杂的逻辑处理,根据需求也推出了StateFlow和SharedFlow这两个特殊的flow。接下来开始看下这几个Flow的特殊之处和应用场景吧~~
官方推荐的Flow数据流流向:
数据流包含三个实体:
flow的基础使用就不介绍了,读者可以查看开头提供的两个链接查看。
在flow内部不允许使用不同的ConretineContext进行emit提交数据,所以想要在内部切换线程可以通过flowOn操作符进行转换
StateFlow
和SharedFlow
是 Flow API,允许数据流以最优方式发出状态更新并向多个使用方发出值。
这两个Flow和普通的Flow不一样, Flow我们知道,只有当调用collect的时候flow传入的函数才会执行,并且每次调用collect都会重新走一遍flow函数(本质是扩展函数),调用collect的时候执行这个扩展函数;但是这两个Flow不一样他们不依赖于外部调用(可配置稍后说明),他们是热流,他们发出的数据会缓存起来当有订阅者的时候再通知订阅者
StateFlow
和 SharedFlow
是发出状态更新并向多个使用方发出值并且可以通过value属性获取当前最新值。类似于观察数据,数据更新,使用方接受最新数据是不是和LiveData很像。确实像,但他比LiveData更强大~~
2.lifecycleScope: 此范围内启动的协程会在 Lifecycle
被销毁时取消;也可以通过when生命周期来指定何时开启,如果 Lifecycle
未至少处于所需的最低状态,则会挂起在这些块内运行的任何协程,注意是挂起而不是销毁时的取消,意味着还是会浪费资源。
一定要注意取消这个词和挂起的区别,挂起其实还是有订阅关系的当flow发射时还是会收到走collect上游并没有取消,但是取消就是协程作用域的取消collect函数不会执行了。
但是我们可以使用repeatOnLifecycle,它当离开某个生命周期的时候进行取消,符合的时候在开启一个新协程(也即会重新执行collect函数是新的订阅者)。
Android官方的警告:倾向于使用
repeatOnLifecycle
API 收集数据流,而不是在launchWhenX
API 内部进行收集。由于后面的 API 会挂起协程,而不是在Lifecycle
处于STOPPED
状态时取消。上游数据流会在后台保持活跃状态,并可能会发出新的项并耗用资源。
官方示例:
将普通flow转换为ShareFlow(StateFlow的一种)通过shareIn操作符 需要传入以下三个参数: (这三个参数)
class NewsRemoteDataSource(...,
private val externalScope: CoroutineScope,
) {
val latestNews: Flow<List<ArticleHeadline>> = flow {
...
}.shareIn(
externalScope,
replay = 1,
started = SharingStarted.WhileSubscribed()
)
}
CoroutineScope
。此作用域函数的生命周期应长于任何使用方,以使共享数据流在足够长的时间内保持活跃状态。(超出该作用域时flow下游逻辑取消)
repeatOnLifecycle针对生命周期取消订阅流的收集(上游)collect函数(符合在开启新协程重新订阅),WhileSubscribed策略配置订阅者超时时间进行取消flow函数(下游) 搭配好这两个一个是订阅者一个是被订阅者的关系处理好业务逻辑
2.SharingStarted.Eagerly
可立即启动提供方(flow函数立马运行),使用 SharingStarted.Lazily
可在第一个订阅者出现后开始共享数据(只有当订阅时才会运行)并且都在externalScope作用域取消时取消收集。
除此之外还可定义其他SharedFlow
行为:
replay
,您可以针对新订阅者重新发送多个之前已发出的值。
onBufferOverflow
,您可以指定相关政策来处理缓冲区中已存满要发送的数据项的情况。默认值为 BufferOverflow.SUSPEND
,这会使调用方挂起。其他选项包括 DROP_LATEST
或 DROP_OLDEST
。
subscriptionCount
属性,获取活跃状态的收集器的数量。
resetReplayCache
函数清空数据缓存,供您在不想回放已向数据流发送的最新信息的情况下使用。