channelFlow的并发emit
1 | fun main() = runBlocking { |
使用channelFlow
可以在不同的上下文中发射值。
用 flow{}
构建器则不行,代码如下
1 | fun main() = runBlocking { |
channelFlow
解释
创建一个冷流,它允许element在不同的上下文中并发地产生.
The resulting flow completes as soon as the code in the block and all its children completes. Use awaitClose
as the last statement to keep it running.
背压措施:A channel with the default buffer size is used. Use the buffer operator on the resulting flow to specify a user-defined value and to control what happens when data is produced faster than consumed, i.e. to control the back-pressure behavior.
awaitClose
显式地,不让channelFlow
的block
块结束。示例如下:
1 | // example1 当the code in the block and all its children completes,channelFlowblock块退出 |
为什么flow内不能切换上下文
并不是不能切换上下文,只是emit
不能在另外的上下文,下面这样的代码还是可以的
1 | fun main() = runBlocking { |
那本文开头的代码为什么不行,据这篇文章所说,是因为如果那样做,collect
的代码块可能在错误的上下文去运行,然后需要写一些样板代码去确保 collect
的代码能在正确的上下文去运行。没太看懂老实说。
最后建议使用 flowOn
操作符去进行上游的上下文的切换。
callbackFlow
callbackFlow
除了强制使用awaitClose
之外,并没有和channelFlow什么不同。callbackFlow
的设计是为了桥接一些旧的API,那些api设计成传callback.
1 | fun flowFrom(api: CallbackBasedApi): Flow<T> = callbackFlow { |
强制使用 awaitClose
是为了让你使用callback api的时候减少bug的发生机会,因为你必须在 awaitClose
处做点什么,这样可以提醒自己。比如说:网络请求的取消,资源的关闭等等。看具体的情况来和 callback
api 互动。
因为在 callback
的回调之中不能使用挂起函数,要发送值就不能用 send
了,可以用 trySend
/ trySendBlocking
, trySend
是立即返回,建议使用trySendBlocking
,可以为返回的 ChannelResult
设置回调。