web-dev-qa-db-ja.com

Kotlin.Flowにアイテムを送信するにはどうすればよいですか(Behaviorsubjectなど)

Kotlin.Flowにアイテムを送信/送信する方法を知りたいので、使用例は次のとおりです。

Consumer/ViewModel/Presenterでは、collect関数を使用してsubscribeできます。

fun observe() {
 coroutineScope.launch {
    // 1. Send event
    reopsitory.observe().collect {
      println(it)
    }
  }
}

しかし、問題はRepository側にあり、RxJavaでは Behaviorsubject を使用してObservable/Flowableとして公開し、次のような新しいアイテムを発行できます。

behaviourSubject.onNext(true)

しかし、私が新しいフローを構築するときはいつでも:

flow {

}

collectしかできません。フローに値を送信するにはどうすればよいですか?

10
Joaquim Ley

サブスクリプション/コレクションでlatest値を取得する場合は、 ConflatedBroadcastChannel を使用する必要があります。

private val channel = ConflatedBroadcastChannel<Boolean>()

これはBehaviourSubjectを複製して、チャネルをフローとして公開します。

// Repository
fun observe() {
  return channel.asFlow()
}

イベント/値をその公開されたFlowに送信するには、このチャネルに単純に送信します。

// Repository
fun someLogicalOp() {
  channel.send(false) // This gets sent to the ViewModel/Presenter and printed.
}

コンソール:

false

afterの後にのみ値を受け取りたい場合は、代わりにBroadcastChannelを使用する必要があります。

それを明確にするために:

RxのPublishedSubjectとして動作します

private val channel = BroadcastChannel<Boolean>(1)

fun broadcastChannelTest() {
  // 1. Send event
  channel.send(true)

  // 2. Start collecting
  channel
    .asFlow()
    .collect {
      println(it)
    }

  // 3. Send another event
  channel.send(false)
}

false

Onlyfalseは、最初のイベントが送信されたときに出力されますbeforecollect { }


RxのBehaviourSubjectとして動作します

private val confChannel = ConflatedBroadcastChannel<Boolean>()

fun conflatedBroadcastChannelTest() {
  // 1. Send event
  confChannel.send(true)

  // 2. Start collecting
  confChannel
    .asFlow()
    .collect {
      println(it)
    }

  // 3. Send another event
  confChannel.send(false)
}

本当

false

両方のイベントが出力され、常にlatest値(存在する場合)を取得します。

また、DataFlow(保留中の名前)でのKotlinのチーム開発について言及したいと思います。

これは コールドストリーム になるため、このユースケースに適しています。

16
Joaquim Ley