有没有一种好方法让频道在关闭后忽略优惠而不抛出异常?
目前,似乎只有尝试捕获才能起作用,因为isClosedForSend
不是原子的。
或者,如果我根本不关闭某个频道,是否会出现问题?对于我的特定用例,我使用渠道作为Android liveata的替代品(因为除了从任何线程发送值并从主线程中侦听之外,我不需要任何其他好处)。在这种情况下,我可以通过生产者来监听频道,该生产者只在我想要的时候发送值,并且只是忽略所有其他输入。
理想情况下,我有一个解决方案,ReceiveChannel
仍然可以听完,但SendChannel
在提供新值时永远不会崩溃。
渠道抛出这个例外by design,作为正确沟通的手段。
如果你绝对必须有这样的东西,你可以使用这种扩展功能:
private suspend fun <E> Channel<E>.sendOrNothing(e: E) {
try {
this.send(e)
}
catch (closedException: ClosedSendChannelException) {
println("It's fine")
}
}
您可以使用以下代码对其进行测试:
val channel = Channel<Int>(capacity = 3)
launch {
try {
for (i in 1..10) {
channel.sendOrNothing(i)
delay(50)
if (i == 5) {
channel.close()
}
}
println("Done")
}
catch (e: Exception) {
e.printStackTrace()
}
finally {
println("Finally")
}
}
launch {
for (c in channel) {
println(c)
delay(300)
}
}
正如您将注意到的那样,由于频道已关闭,制作人将开始打印“很好”,但消费者仍然可以阅读前5个值。
关于你的第二个问题:这取决于。
频道没有这么大的开销,也没有暂停的协同程序。但是你知道,泄漏是泄漏。
我最终将an issue发布到了repo,解决方案是使用BroadcastChannel
。你可以通过ReceiveChannel
创建一个新的openSubscription
,关闭它不会关闭SendChannel
。
这更准确地反映了RxJava的PublishSubject