[英]PublishSubject with Kotlin coroutines (Flow)
我使用了一个 PublishSubject,我正在向它发送消息,同时我也在监听结果。 它完美无缺,但现在我不确定如何使用 Kotlin 的协程(流或通道)做同样的事情。
private val subject = PublishProcessor.create<Boolean>>()
...
fun someMethod(b: Boolean) {
subject.onNext(b)
}
fun observe() {
subject.debounce(500, TimeUnit.MILLISECONDS)
.subscribe { /* value received */ }
}
由于我需要 debounce 运算符,我真的很想对流做同样的事情,所以我创建了一个通道,然后我尝试从该通道创建一个流并监听变化,但我没有得到任何结果。
private val channel = Channel<Boolean>()
...
fun someMethod(b: Boolean) {
channel.send(b)
}
fun observe() {
flow {
channel.consumeEach { value ->
emit(value)
}
}.debounce(500, TimeUnit.MILLISECONDS)
.onEach {
// value received
}
}
怎么了?
Flow
是一个冷异步流,就像一个Observable
。
流上的所有转换,例如
map
和filter
都不会触发流收集或执行,只有终端操作符(例如single
)会触发它。
onEach
方法只是一个转换。 因此,您应该将其替换为终端流运算符collect
。 您也可以使用BroadcastChannel
来获得更清晰的代码:
private val channel = BroadcastChannel<Boolean>(1)
suspend fun someMethod(b: Boolean) {
channel.send(b)
}
suspend fun observe() {
channel
.asFlow()
.debounce(500)
.collect {
// value received
}
}
更新:在提出问题时,有两个参数的debounce
过载(如问题中所示)。 已经没有了。 但是现在有一个以毫秒(Long)为单位接受一个参数。
Kotlin 协程中的 ArrayBroadcastChannel 与 PublishSubject 最相似。
与 PublishSubject 不同,背压内置于协程通道中,这就是缓冲区容量的来源。这个数字实际上取决于通道用于哪个用例。 对于大多数正常用例,我只使用 10 个,这应该绰绰有余。 如果您将事件推送到此通道的速度比使用它的接收器更快,则可以提供更多容量。
它应该是SharedFlow/MutableSharedFlow
为PublishProcessor/PublishRelay
和StateFlow/MutableStateFlow
为BehaviorProcessor/BehaviorRelay
。
// initial value to constructor
private val _myFlow = MutableStateFlow<Boolean>("")
// expose as Flow<Boolean>
val myFlow = _myFlow
...
fun someMethod(b: Boolean) {
_myFlow.value = b
}
// this must be either `suspend` fun or create coroutine (`.launch{}`) inside to be able to `.collect`
suspend fun observe() {
myFlow.debounce(500)
.collect { }
}
MutableStateFlow
在设置新值时使用.equals
比较,因此它不会一次又一次地发出相同的值(与使用引用比较的distinctUntilChanged
相比)
编辑:我不确定_myFlow.value=b
与_myFlow.emit(b)
。 有人开悟
实际上BroadcastChannel
已经过时了,Jetbrains 改变了他们的方法,改为使用SharedFlows
。 这更干净,更容易实现并解决了很多痛点。
本质上,您可以像这样实现相同的目标。
class BroadcastEventBus {
private val _events = MutableSharedFlow<Event>()
val events = _events.asSharedFlow() // read-only public view
suspend fun postEvent(event: Event) {
_events.emit(event) // suspends until subscribers receive it
}
}
要了解更多信息,请查看 Roman 的 Medium 文章。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.