11

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

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"、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 にその動作をエミュレートできるものはありますか?

4

3 に答える 3

3

ここでの問題は、戻ったcollectときにのみ呼び出されgetDataFromServerます。

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

これらの関数を書いた方法は、次のように書いても機能します。

flow<String> {
    emitAll(getCached())
    emitAll(getFromServer())
}

このステートメントはすぐに完了し、コールド フローが返されます。それを呼び出すcollectと、最初getCached()にキャッシュされた値を呼び出しgetFromServer()て発行し、次にサーバーの応答を呼び出して発行します。


上記のソリューションは、キャッシュされた値を消費した後にのみサーバー呼び出しを開始します。2 つのフローを同時にアクティブにする必要がある場合は、 を使用しますflatMapMerge

上記の基本的な問題を修正し、フローを返す関数を中断しないようにすると、必要なのは次のとおりです。

flowOf(getCached(), getFromServer()).flattenMerge()

何らかの理由でそれができない場合は、emitAll各呼び出しにラッパーを追加する必要があります。

flowOf(
    flow { emitAll(getCached()) }, 
    flow { emitAll(getFromServer()) }
).flattenMerge()
于 2020-02-13T12:43:19.393 に答える