耗材渠道
Consumable channel
用例
Android 片段消耗 ReceiveChannel<T>
中的 T
项。一旦消耗,T
s 应该从 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 不支持 UNLIMITED
和 0
(用于 rendez-vous) =]
您也可以使用 ConflatedBroadcastChannel
,它始终为新订阅者提供最新价值,就像 LiveData
所做的那样。
顺便说一句,如果您的新 Fragment
实例仅接收最新值,这有什么大不了的吗?如果没有,那么直接使用 ConflatedBroadcastChannel
。否则,BroacastChannel
中的 none 可能适合您的用例(尝试一下,看看是否得到您正在寻找的行为)。
用例
Android 片段消耗 ReceiveChannel<T>
中的 T
项。一旦消耗,T
s 应该从 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 不支持 UNLIMITED
和 0
(用于 rendez-vous) =]
您也可以使用 ConflatedBroadcastChannel
,它始终为新订阅者提供最新价值,就像 LiveData
所做的那样。
顺便说一句,如果您的新 Fragment
实例仅接收最新值,这有什么大不了的吗?如果没有,那么直接使用 ConflatedBroadcastChannel
。否则,BroacastChannel
中的 none 可能适合您的用例(尝试一下,看看是否得到您正在寻找的行为)。