web-dev-qa-db-fra.com

Le flux de Kotlin exécute deux appels d'API en parallèle et collectez chaque résultat car il arrive

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?

8
Abhishek Bansal

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())
}
1
Marko Topolnik

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.

0
ragdroid

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) }
}
0
Abhishek Bansal