我正在尝试将RX的一部分代码重构为协程,但是尽管我付出了所有努力,但我还是觉得迷路了。
所以我创建了PublishSubject,我正在向它发送消息,而且我也在听结果。它可以完美地工作,但是现在我不确定如何对协程(流或通道)执行相同的操作。
private val subject = PublishProcessor.create<Boolean>>()
...
fun someMethod(b: Boolean) {
subject.onNext(b)
}
fun observe() {
subject.debounce(500, TimeUnit.MILLISECONDS)
.subscribe {
// value received
}
}
因为我需要使用反跳运算符,所以我真的想对流执行相同的操作,因此我创建了通道,然后尝试从该通道创建流并听取更改,但没有得到任何结果。
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
}
}
我怎么了?
答案 0 :(得分:1)
Flow
是一个冷的异步流,就像Obserable
一样。
流上的所有转换(例如
map
和filter
都不会触发流的收集或执行,只有终端操作员(例如single
)会触发流。
onEach
方法只是一个转换。因此,您应该使用终端流量运算符collect
代替它。另外,您可以使用BroadcastChannel
来获得更简洁的代码:
private val channel = BroadcastChannel<Boolean>(1)
fun someMethod(b: Boolean) {
channel.send(b)
}
fun observe() {
channel
.asFlow()
.debounce(500, TimeUnit.MILLISECONDS)
.collect {
// value received
}
}
答案 1 :(得分:1)
对于 PublishProcessor/PublishRelay
应该是 SharedFlow/MutableSharedFlow
,对于 BehaviorProcessor/BehaviorRelay
应该是 StateFlow/MutableStateFlow
。
// 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)
的区别。有人开导
答案 2 :(得分:0)
Kotlin协程中的ArrayBroadcastChannel与PublishSubject最相似。
与PublishSubject不同,反压是内置在协程通道中的,这就是缓冲容量的来源。此数字实际上取决于通道用于的用例。对于大多数正常用例,我只用了10个,应该绰绰有余。如果您将事件推送到此频道的速度比接收者消费事件的速度快,则可以提供更多的容量。
答案 3 :(得分:0)
实际上 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 文章。