Kotlin
Flows
を使用して、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には、その動作をエミュレートできる何かがありますか?
設計で最初に問題となるのは、Flow-returning関数も中断可能であることです。これが2層のサスペンド性です。関数は遅延なしでフローを返す必要があり、フロー自体は着信時にアイテムを生成する必要があります。このガイドラインに従えば、最初のコードはすでに機能しています。
これらの関数の記述方法は、次のように記述しても機能します。
flow<String> {
emitAll(getCached())
emitAll(getFromServer())
}
最近、merge
演算子がKotlinコルーチンバージョン1.3.3
に追加されました。これがマージされた [〜#〜] pr [〜#〜] です。
マージ演算子を使用すると、到着時に結果を取得できるはずです。
ダウンストリームが処理を開始するために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) }
}