web-dev-qa-db-ja.com

Kotlin Flowは2つのAPI呼び出しを並行して実行し、到着時に各結果を収集します

KotlinFlowsを使用して、API呼び出しのキャッシュとネットワーク戦略を実装しようとしています。これが私が今試していることです

_flowOf(
 remoteDataSource.getDataFromCache() // suspending function returning Flow<Data>
   .catch { error -> Timber.e(error) },
 remoteDataSource.getDataFromServer() // suspending function returning Flow<Data>
).flattenConcat().collect {
  Timber.i("Response Received")
}
_

ここでの問題はcollectが呼び出されるのは、getDataFromServerが戻ったときだけです。私の期待は、キャッシュから最初のイベントを取得し、数ミリ秒後にサーバーから2番目のイベントを取得することです。この場合、_"Response Received"_ getsは2回出力されますが、すぐに次々と出力されます。

この他のバリアントでは、_"Response Received"_は、getDataFromServer()が返された後に一度だけ出力されます。

_ remoteDataSource.getDataFromCache() // suspending function returning Flow<Data>
  .catch { error -> Timber.e(error) }
  .flatMapConcat {
    remoteDataSource.getDataFromServer() // suspending function returning Flow<Data>
  }
  .collect {
    Timber.i("Response Received")
  }
_

以前はRxJavaのFlowable.concat()を使用していましたが、完全に機能していました。 Kotlin Flowsには、その動作をエミュレートできる何かがありますか?

5
Abhishek Bansal

設計で最初に問題となるのは、Flow-returning関数も中断可能であることです。これが2層のサスペンド性です。関数は遅延なしでフローを返す必要があり、フロー自体は着信時にアイテムを生成する必要があります。このガイドラインに従えば、最初のコードはすでに機能しています。

これらの関数の記述方法は、次のように記述しても機能します。

flow<String> {
    emitAll(getCached())
    emitAll(getFromServer())
}
1
Marko Topolnik

最近、merge演算子がKotlinコルーチンバージョン1.3.3に追加されました。これがマージされた [〜#〜] pr [〜#〜] です。

マージ演算子を使用すると、到着時に結果を取得できるはずです。

0
ragdroid

ダウンストリームが処理を開始するためにflowOf(someOperation())someOperation()を完了する必要がある場合に判明します。 RxJavaワールドのObservable.just(someOperation())に似ています。

2番目のシナリオでは、flatMapConcatは実際にはtransform演算子であるため、最終的に処理された出力を返します。

Flowの世界では、ネイティブのconcatのような演算子が不足しているようです。これが私が最後にこの問題を解決した方法です

flow {
   remoteDataSource.getDataFromCache()
   .catch { error -> Timber.e(error) }
   .onCompletion {
       remoteDataSource.getDataFromServer()
            .collect {
                 emit(it)
            }
    }.collect { emit(it) }
}
0
Abhishek Bansal