Kotlin 消耗品通道 用例

Kotlin 消耗品通道 用例,kotlin,kotlinx.coroutines,Kotlin,Kotlinx.coroutines,Android片段,从ReceiveChannel消费T项。一旦消费,应将Ts从ReceiveChannel中删除 我需要一个ReceiveChannel,支持从中消费物品。它应该起FIFO队列的作用 我当前从UI连接到频道,如: launch(uiJob) { channel.consumeEach{ /** ... */ } } 我通过调用uiJob.cancel()来分离 期望的行为: val channel = Channel<Int>(UNLIMITED) channe

Android片段,从
ReceiveChannel
消费
T
项。一旦消费,应将
T
s从
ReceiveChannel
中删除

我需要一个
ReceiveChannel
,支持从中消费物品。它应该起FIFO队列的作用

我当前从UI连接到频道,如:

launch(uiJob) { channel.consumeEach{ /** ... */ } }
我通过调用
uiJob.cancel()
来分离

期望的行为:

val channel = Channel<Int>(UNLIMITED)

channel.send(1)
channel.send(2)
// ui attaches, receives `1` and `2`
channel.send(3) // ui immediately receives `3`
// ui detaches
channel.send(4)
channel.send(5)
// ui attaches, receiving `4` and `5`
val通道=通道(无限制)
频道发送(1)
频道发送(2)
//ui附加并接收'1'和'2'`
channel.send(3)//ui立即接收'3`
//用户界面分离
频道发送(4)
频道发送(5)
//用户界面连接,接收'4'和'5'`
不幸的是,当我从通道分离时,通道关闭。这会导致
.send(4)
.send(5)
抛出异常,因为通道已关闭。我希望能够从通道中分离并使其保持可用。我该怎么做


Channel(UNLIMITED)
非常适合我的使用案例,除了在取消订阅时关闭频道。我希望频道保持开放。这可能吗?

Channel.consumereach
方法调用
Channel.consumer
方法,该方法在文档中有以下行:

通过在执行块后始终调用cancel,确保给定块使用给定通道中的所有元素

因此,解决方案就是不要使用
消费[每种]
。例如,您可以执行以下操作:


launch(uiJob){for(it in channel){/**…*/}}
您可以使用
BroadcastChannel
。但是,您需要指定一个有限的大小(例如
1
),因为
广播频道不支持
UNLIMITED
0
(对于rendez VOU)

您还可以使用
ConflatedBroadcastChannel
,它总是向新订户提供它所拥有的最新值,就像
LiveData
正在做的那样


顺便说一句,如果新的
Fragment
实例只接收最新的值,这有什么大不了的吗?如果没有,那么只需使用
合并的DBroadcastChannel
。否则,
BroacastChannel
s中的任何一个都不适合您的用例(尝试一下,看看您是否获得了所需的行为)。

我已经有了一个
confollatedbroadcastchannel
。需要一个“可消费”频道向UI发送副作用,如显示烤面包片或振动设备。您可以在
ViewState
中添加一个
markHandled()
函数,该函数翻转一个
hasBeenHandled
布尔属性,该属性是公开只读的,在尝试处理事件之前,你检查它是否已经用if处理过。这是有效的。这里的缺点是接收器可以关闭通道,这不是期望的行为。对不起,这是什么意思?我希望
ReceiveChannel
是只读的,但它不是!能够关闭它会使它变为可变的我想你可以在没有关闭方法的情况下将它包装到另一个接口中?