J'essaie de mettre en œuvre le cache, puis une stratégie réseau pour mon appel d'API à l'aide de Kotlin
_ Flows
. Voici ce que j'essaye maintenant
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")
}
Problème ici est collect
est seulement appelé lorsque getDataFromServer
revient. Mon attente est que je devrais obtenir le premier événement du cache, puis un deuxième événement du serveur après quelques millisecondes. Dans ce cas "Response Received"
Est imprimé deux fois mais immédiatement après l'autre.
Dans cette autre variante "Response Received"
Est uniquement imprimée une fois que cela est après getDataFromServer()
retourne.
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")
}
J'utilisais Flowable.concat()
avant et j'avais déjà fonctionné parfaitement. Y a-t-il quelque chose dans les flux de kotlin qui peuvent imiter ce comportement?
La première chose problématique avec votre conception est que la fonction de retour d'écoulement est également suspendue. C'est deux couches de suspension. Les fonctions doivent revenir à des flux sans retard et les flux eux-mêmes devraient émettre des éléments tels qu'ils entrent. Si vous avez suivi cette ligne directrice, votre code initial fonctionnerait déjà.
La façon dont vous avez écrit ces fonctions, ils peuvent toujours travailler si vous écrivez ceci:
flow<String> {
emitAll(getCached())
emitAll(getFromServer())
}
Récemment, merge
Opérateur a été ajouté à la version Kotlin Coroutines 1.3.3
. Voici la fusible [~ # ~ # ~] PR [~ # ~] .
À l'aide de l'opérateur de fusion, vous devriez pouvoir obtenir le résultat de l'arrivée.
S'avère en cas de flowOf(someOperation())
someOperation()
doit être rempli pour en aval pour commencer le traitement. C'est comme Observable.just(someOperation())
dans RxJava
monde.
Dans le deuxième scénario flatMapConcat
est en fait un opérateur transform
afin qu'il renvoie évidemment la production traitée finale.
Il semble y avoir le manque de natif concat
comme des opérateurs dans le monde du flux. C'est comme ça que j'ai résolu ce problème à la fin
flow {
remoteDataSource.getDataFromCache()
.catch { error -> Timber.e(error) }
.onCompletion {
remoteDataSource.getDataFromServer()
.collect {
emit(it)
}
}.collect { emit(it) }
}