私は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 */ }
}
デバウンス演算子が必要なので、フローでも同じことをしたかったので、チャネルを作成してから、そのチャネルからフローを作成して変更をリッスンしようとしましたが、結果が得られません。
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
は、Obserable
と同様に、コールド非同期ストリームです。
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, TimeUnit.MILLISECONDS)
.collect {
// value received
}
}
KotlinコルーチンのArrayBroadcastChannelは、PublishSubjectに最も類似したものです。
PublishSubjectとは異なり、バックプレッシャーはコルーチンチャネルに組み込まれており、そこにバッファー容量が入ります。この数は、チャネルが使用されているユースケースに実際に依存します。ほとんどの通常の使用例では、10以上で十分です。イベントをこのチャネルにプッシュするのが、それを消費するレシーバーよりも高速である場合は、より多くの容量を提供できます。