Lorsque vous utilisez la carte vs flatMap dans RxJava?
De le faire lorsque vous utilisez la carte vs flatMap dans RxJava?
Dire par exemple, nous voulons carte Fichiers contenant JSON dans les Chaînes qui contiennent le JSON--
À l'aide de la carte, nous avons affaire à l'Exception d'une certaine manière. Mais comment?:
Observable.from(jsonFile).map(new Func1<File, String>() {
@Override public String call(File file) {
try {
return new Gson().toJson(new FileReader(file), Object.class);
} catch (FileNotFoundException e) {
//So Exception. What to do ?
}
return null; //Not good :(
}
});
À l'aide de flatMap, c'est beaucoup plus détaillé, mais nous pouvons en avant le problème de la chaîne de phénomènes Observables et gérer l'erreur si nous choisissons quelque part d'autre et même réessayer:
Observable.from(jsonFile).flatMap(new Func1<File, Observable<String>>() {
@Override public Observable<String> call(final File file) {
return Observable.create(new Observable.OnSubscribe<String>() {
@Override public void call(Subscriber<? super String> subscriber) {
try {
String json = new Gson().toJson(new FileReader(file), Object.class);
subscriber.onNext(json);
subscriber.onCompleted();
} catch (FileNotFoundException e) {
subscriber.onError(e);
}
}
});
}
});
J'aime la simplicité de la carte, mais la gestion des erreurs de flatmap (pas le niveau de verbosité). Je n'ai pas vu de meilleures pratiques à ce sujet flottant autour et je suis curieux de voir comment ce est utilisé dans la pratique.
Vous devez vous connecter pour publier un commentaire.
map
transformer un événement à un autre.flatMap
transformer un événement à zéro, un ou plusieurs événements. (ceci est pris à partir de IntroToRx)Que vous souhaitez transformer votre json à un objet, à l'aide de la carte devrait être suffisant.
Traiter avec la FileNotFoundException est un autre problème (à l'aide de la carte ou flatmap ne résout pas ce problème).
Pour résoudre votre problème d'Exception, il suffit de jeter un Non vérifié exception : RX fera appel à la onError gestionnaire pour vous.
exactement la même version avec flatmap :
Vous pouvez revenir aussi, dans le flatMap version une nouvelle Observables, c'est juste une erreur.
subscriber.onError()
etc. Tous les exemples que j'ai vu ont acheminé les erreurs de cette façon. N'est-ce pas important?OnErrorThrowable
sontprivate
et vous avez besoin d'utiliserOnErrorThrowable.from(e)
à la place.FlatMap se comporte comme une carte, la différence est que la fonction à laquelle elle s'applique renvoie une observable lui-même, il est donc parfaitement adapté à la carte sur les opérations asynchrones.
Dans le sens pratique, la fonction Map applique tout simplement une transformation en chaîne de réponse (pas de renvoi d'un Observable); tandis que la fonction FlatMap s'applique retourne un
Observable<T>
, c'est pourquoi FlatMap est recommandé si vous envisagez de faire un appel asynchrone à l'intérieur de la méthode.Résumé:
Un exemple peut être vu ici: http://blog.couchbase.com/why-couchbase-chose-rxjava-new-java-sdk .
Couchbase Java 2.X Client utilise Rx à fournir des appels asynchrones de façon pratique. Depuis qu'il utilise Rx, il a les méthodes carte et FlatMap, l'explication dans leur documentation pourrait être utile pour comprendre le concept général.
Pour gérer les erreurs, remplacer onError sur votre susbcriber.
Il peut être utile de regarder ce document: http://blog.danlew.net/2014/09/15/grokking-rxjava-part-1/
Une bonne source sur la façon de gérer les erreurs avec la RX peut être trouvé à: https://gist.github.com/daschl/db9fcc9d2b932115b679
Dans votre cas, vous avez besoin de la carte, car il est à seulement 1 entrée et 1 sortie.
carte de fonction fournie accepte simplement un élément et retourne un élément qui sera émise plus (une seule fois) vers le bas.
flatMap fourni par la fonction accepte un élément, puis renvoie un "Observable", ce qui signifie que chaque élément de la nouvelle "Observables" sera émis séparément plus bas.
Peut être code de clarifier les choses pour vous:
De sortie:
La façon dont je pense à ce sujet est que vous utilisez
flatMap
lorsque la fonction que vous vouliez mettre à l'intérieur demap()
retourne unObservable
. Dans ce cas, vous pourriez toujours essayer de l'utilisermap()
mais il serait judicieux. Laissez-moi vous expliquer pourquoi.Si dans de tels cas, vous avez décidé de rester avec
map
, vous obtiendrez uneObservable<Observable<Something>>
. Par exemple, dans votre cas, si nous avons utilisé un imaginaire RxGson de la bibliothèque, qui a retourné uneObservable<String>
detoJson()
méthode (au lieu de simplement retourner unString
), il devrait ressembler à ceci:À ce stade, il serait assez difficile de
subscribe()
à une telle observable. A l'intérieur, vous obtiendrez uneObservable<String>
à qui vous auriez encore besoin desubscribe()
pour obtenir de la valeur. Ce qui n'est pas pratique et agréable à regarder.Afin de la rendre utile une idée est "d'aplatir" ce observables des observables (vous pourriez commencer à voir où le nom _flat_Map vient). RxJava fournit un peu de moyens pour aplatir observables et par souci de simplicité, supposons fusion est ce que nous voulons. Fusion prend essentiellement en un tas de phénomènes observables et émet à chaque fois que l'un d'eux émet. (Beaucoup de gens diraient commutateur serait une meilleure défaut. Mais si vous êtes émet juste une seule valeur, il n'a pas d'importance de toute façon.)
Donc à la modification de notre fragment de code précédent, nous aurions:
C'est beaucoup plus utile, parce que souscrire à cette (ou de cartographie, de filtrage ou de...), vous obtenez juste le
String
valeur. (Aussi, vous l'esprit, une telle variante demerge()
n'existe pas dans RxJava, mais si vous comprenez l'idée de fusionner alors j'espère que vous comprenez comment cela pourrait fonctionner.)Donc, fondamentalement, parce que de telles
merge()
devrait probablement toujours être utile lorsqu'il réussit unmap()
retour d'un observable et donc vous n'avez pas à taper encore et encore,flatMap()
a été créé comme une abréviation. Il applique la fonction de mappage juste normalmap()
serait, mais plus tard, au lieu d'émettre les valeurs renvoyées il a également "aplatit" (ou de fusion) entre eux.C'est le grand cas d'utilisation. Il est le plus utile dans une base de code qui utilise Rx allover l'endroit et vous avez de nombreuses méthodes de retour observables, qui vous voulez à la chaîne avec d'autres méthodes retournant observables.
Dans votre cas d'utilisation, il arrive à être utile, parce que
map()
ne peut transformer une valeur émise dansonNext()
en une autre valeur émise dansonNext()
. Mais il ne peut pas la transformer en de multiples valeurs, aucune valeur ou une erreur. Et comme akarnokd a écrit dans sa réponse (et vous l'esprit qu'il est beaucoup plus intelligent que moi, sans doute en général, mais au moins quand il s'agit de RxJava) vous ne devriez pas lancer des exceptions à partir de votremap()
. Donc, au lieu de cela, vous pouvez utiliserflatMap()
etquand tout va bien, mais
quand quelque chose tombe en panne.
Voir sa réponse complète pour un extrait: https://stackoverflow.com/a/30330772/1402641
Ici est une simple pouce de la règle de que j'utilise m'aider à décider quand utiliser
flatMap()
surmap()
en Rx duObservable
.Une fois que vous venez à une décision que vous allez employer une
map
transformation, vous devez écrire votre transformation de code pour revenir à l'Objet de droit?Si ce que vous êtes de retour en tant que résultat final de votre transformation est:
un non-observables objet, vous devez utiliser juste
map()
. Etmap()
encapsule l'objet dans un Observable et l'émet.un
Observable
objet, vous devez alors utiliserflatMap()
. EtflatMap()
déballe le Observables, récupère l'objet retourné, l'enveloppe avec ses propres Observables et l'émet.Dire, par exemple, nous avons une méthode titleCase(String inputParam) qui renvoie Intitulé Tubé Chaîne de l'objet de l'apport param. Le type de retour de cette méthode peut être
String
ouObservable<String>
.Si le type de retour de
titleCase(..)
devaient être simpleString
, alors vous devriez utilisermap(s -> titleCase(s))
Si le type de retour de
titleCase(..)
devaient êtreObservable<String>
, alors vous devriez utiliserflatMap(s -> titleCase(s))
Espère que précise.
La question est de le faire Lorsque vous utilisez la carte vs flatMap dans RxJava?. Et je pense qu'une simple démo est plus spécifique.
Où vous voulez convertir un élément émis à un autre type , dans votre cas, la conversion du fichier à Chaîne, d'une carte et flatMap peut à la fois travailler. Mais je préfère la carte de l'opérateur, car il est plus clairement.
Toutefois, dans certains endroit,
flatMap
peut faire de la magie de travail maismap
ne le peuvent pas. Par exemple, je souhaite obtenir des informations pour un utilisateur, mais je dois d'abord obtenir sa carte d'identité lors de la connexion de l'utilisateur dans. Évidemment, j'ai besoin de deux demandes et ils sont dans l'ordre.Nous allons commencer.
Voici deux méthodes, l'une pour la connexion retourné
Response
, et un autre pour récupérer les infos de l'utilisateur.Comme vous le voyez, en fonction flatMap s'applique, j'ai d'abord obtenir l'id d'utilisateur à partir
Response
de récupérer les infos de l'utilisateur. Lorsque deux demandes sont finis, nous pouvons faire notre travail comme la mise à jour de l'INTERFACE utilisateur ou des données de sauvegarde dans la base de données.Toutefois, si vous utilisez
map
vous ne pouvez pas écrire de telles nice code. En un mot,flatMap
peut nous aider à sérialiser les demandes.Je voulais juste ajouter qu'avec
flatMap
, vous n'avez pas vraiment besoin d'utiliser votre propre Observables à l'intérieur de la fonction et vous pouvez compter sur la norme d'usine méthodes/opérateurs:En général, vous devriez éviter de les jeter (à l'Exécution) des exceptions de onXXX des méthodes et des rappels si possible, même si nous avons mis autant de garanties que nous pourrions en RxJava.
Dans ce scénario, l'utilisation de la carte, vous n'avez pas besoin d'un nouveau Observables pour elle.
vous devriez utiliser les Exceptions.propager, ce qui est un wrapper de sorte que vous pouvez envoyer ces checked exceptions à la rx mécanisme
Vous devrez alors gérer cette erreur dans l'abonné
Il y a un super post pour elle: http://blog.danlew.net/2015/12/08/error-handling-in-rxjava/
Dans certains cas, vous pouvez avoir de la chaîne des observables, dans lequel votre observable serait de retour une autre observable. 'flatmap de type déballe le deuxième observables qui est enterré dans la première, et vous permettent d'accéder directement aux données de la deuxième observable est de cracher lors de la souscription.