Kotlin Flow、Channel 和 ChannelFlow 的区别
Kotlin Flow、Channel 和 ChannelFlow 的区别
- 冷流(冷数据流)是非即时的、懒惰的,按需执行操作(生成数据),不会提前准备好数据,而是在需要时候才生产(惰性),比如 Flow 需要依赖 collect 收集操作来触发数据的流动(只有在有订阅者订阅时才会启动数据的生产和发送)
- 热流(热数据流)是急切的、即时的、活跃的,主动产生数据,比如 List 之类的集合(创造元素行为独立于消费者)、ShareFlow、StateFlow(在创建时即持有初始值,调用 stateFlow.value = newState 更新状态值)和 Channel 等(不管有没有订阅者都会持续产生并发射数据)
- 冷流是不共享的,没有缓存机制,多个订阅者间的数据流是相互独立的(每个订阅者从头开始执行流的逻辑,不共享状态),通常情况下订阅者(消费者)停止监听或者生产代码结束后数据流就自动关闭了
- 热流是共享的,有缓存机制的,多个订阅者可以共享同一个数据流(新订阅者加入时,直接接收当前最新值,而非从头开始,多消费者可以状态共享),通常情况下数据流不会自动关闭,需要手动关闭
Flow
- Flow 提供了一种以声明式的方式来处理异步数据流,是一种表示异步流的抽象概念,类似于 RxJava 中的 Observable
- Flow 通过 emit 发送数据,通过 collect 接收数据,两个都是挂起函数,每次收集时都会重新执行流构建(流生成器)的代码
- Flow 通常与协程生命周期(作用域)绑定,协程取消时 Flow 的执行也会停止,所以可以通过取消协程来取消整个流的操作
- Flow 可处理背压,比如通过 buffer 操作符增强、子类 SharedFlow 支持配置缓存容量
- Flow 的数据发送和接收是顺序的,没有缓冲机制(没有缓冲区),每次 emit 发送的数据都必须在下一次 emit 调用之前被消耗掉,因此每次 emit 都必须排队,发送和消费是同步进行的,消费的耗时会减慢发送的速度
- Flow 提供了丰富的操作符(支持丰富的数据处理操作),另外 Flow 的数据流是不可变的,一旦创建,不能修改
- Flow 常用于简单的异步数据流处理,常用于从网络请求或数据库中获取数据等场景,适用于数据生产者和消费者速度匹配的场景
Channel
- Channel 提供了一种协程间的通信方式,用于实现跨协程传递数据,是协程间通信的机制,类似于 Java 中的 BlockQueue 阻塞队列(但 Channel 是非阻塞的,通过挂起协程实现非阻塞通信)
- Channel 通过 send 发送数据,通过 receive 接收数据,两个都是挂起函数,一经创建就已经准备发送和接收数据,数据一旦发送就会被存储,是独立于收集操作而存在的(生产者和消费者相互独立)
- Channel 通常需要显式关闭,否则很容易造成资源泄漏(所以 Google 推荐优先使用 Flow 而不是 Channel)
- Channel 具有缓冲区(默认缓冲区大小是 64),通过缓冲区实现背压处理,通过缓冲区来处理生产者和消费者速度不匹配的问题
- Channel 支持并发,多个协程可以同时向 Channel 发送数据,也可以有多个协程同时从 Channel 接收数据,利用协程的并发能力,将多个 Flow 的收集操作并行执行
- Channel 常用于实现生产者-消费者模式的数据交换(一个协程可以作为生产者向 Channel 发送数据,而另一个协程可以作为消费者从 Channel 接收数据),适合用于协程间的直接通信,尤其是事件驱动、任务队列等需要实时传递数据的场景
ChannelFlow
- ChannelFlow 是一种特殊的 Flow(实现了 Flow 接口),使用 Channel 来生成和发送数据(传递数据),结合了 Flow 的特点(比如惰性特性等)和 Channel 的特点(比如跨协程通信、缓冲区等),虽然 ChannelFlow 底层是基于 Channel 实现的(将 Channel 的生产者逻辑封装为 Flow),但在使用上表现为冷流(只有被收集时才开始工作)
- ChannelFlow 中使用 send 发送数据,send 也是挂起函数
- ChannelFlow 适用于需要处理高并发、高吞吐量的异步数据流、需要在 Flow 中实现复杂的生产者逻辑(如动态缓冲、动态背压策略)或者需要缓冲机制来处理生产者和消费者速度不匹配的问题
总结
- Flow 适用于一次性数据流处理,需要对数据流进行一些复杂操作(比如数据转换、过滤等),比如网络响应、数据库查询的场景
- Channel 更侧重于协程之间的直接通信,是一种低层次的异步数据传递机制,比如用于实现复杂的生产者-消费者模式
- ChannelFlow 是 Flow 的一种,更侧重于数据的流式处理,结合两者优势(可以利用 Flow 的各种操作符进行数据转换和处理、支持缓冲、线程切换和复杂流操作,比如实时传感器的数据场景)