耗材渠道

Consumable channel

用例

Android 片段消耗 ReceiveChannel<T> 中的 T 项。一旦消耗,Ts 应该从 ReceiveChannel<T>.

中移除

我需要一个 ReceiveChannel<T> 支持从中消费物品。它应该用作 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`

不幸的是,当我从频道分离时,频道关闭了。这会导致 .send(4).send(5) 抛出异常,因为通道已关闭。我希望能够从通道中分离出来并让它保持可用状态。我该怎么做?

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

Channel.consumeEach 方法调用 Channel.consume 方法,该方法在文档中有此行:

Makes sure that the given block consumes all elements from the given channel by always invoking cancel after the execution of the block.

所以解决办法就是干脆不使用consume[Each]。例如你可以这样做:

launch(uiJob) { for (it in channel) { /** ... */ } }

您可以使用 BroadcastChannel。但是,您需要指定一个有限的大小(例如 1),因为 BroadcastChannel.[=20 不支持 UNLIMITED0(用于 rendez-vous) =]

您也可以使用 ConflatedBroadcastChannel,它始终为新订阅者提供最新价值,就像 LiveData 所做的那样。

顺便说一句,如果您的新 Fragment 实例仅接收最新值,这有什么大不了的吗?如果没有,那么直接使用 ConflatedBroadcastChannel。否则,BroacastChannel 中的 none 可能适合您的用例(尝试一下,看看是否得到您正在寻找的行为)。