繁体   English   中英

PublishSubject 与 Kotlin 协程(流程)

[英]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

流上的所有转换,例如mapfilter都不会触发流收集或执行,只有终端操作符(例如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 最相似。

  1. 与 PublishSubject 一样,一个 ArrayBroadcastChannel 可以有多个订阅者,并且所有活动订阅者都会立即收到通知。
  2. 与 PublishSubject 一样,如果此时没有活动订阅者,推送到此频道的事件将丢失。

与 PublishSubject 不同,背压内置于协程通道中,这就是缓冲区容量的来源。这个数字实际上取决于通道用于哪个用例。 对于大多数正常用例,我只使用 10 个,这应该绰绰有余。 如果您将事件推送到此通道的速度比使用它的接收器更快,则可以提供更多容量。

它应该是SharedFlow/MutableSharedFlowPublishProcessor/PublishRelayStateFlow/MutableStateFlowBehaviorProcessor/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 文章。

Roman Elizarov 的“共享流、广播频道”

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM