Les opérateurs sont utilisés pour résoudre le problème de la transformation d'objets observables. Les opérateurs sont utilisés pour modifier les événements émis par l'observable entre l'observable et l'abonné final. Rxjava fournit de nombreux opérateurs utiles.
Par exemple, l'opérateur de carte est utilisé pour convertir un événement en un autre.
Observable.Just ("Hello, World!") .Map (new func1 <String, String> () {@Override public String Call (String S) {return s + "-dan";}}) .subscribe (s -> System.out.println (s)); L'utilisation de lambda peut être simplifiée à
Observable.Just ("Hello, World!") .Map (S -> S + "-DAN") .Subscribe (S -> System.out.println (S));N'est-ce pas cool? L'opérateur MAP () est utilisé pour transformer l'objet observable. L'opérateur de carte renvoie un objet observable, de sorte qu'un appel de chaîne peut être mis en œuvre, et l'opérateur de carte est utilisé plusieurs fois sur un objet observable, et enfin les données les plus simples sont transmises à l'objet abonné.
L'opérateur de carte avancé
Ce qui est plus intéressant à propos de l'opérateur de carte, c'est qu'il n'a pas à renvoyer le type renvoyé par l'objet observable. Vous pouvez utiliser l'opérateur de carte pour renvoyer un objet observable qui émet le nouveau type de données.
Par exemple, dans l'exemple ci-dessus, l'abonné ne se soucie pas de la chaîne retournée, mais veut la valeur de hachage de la chaîne.
Observable.Just ("Hello, World!") .Map (new func1 <String, Integer> () {@Override public Integer Call (String S) {return s.hashcode ();}}) .subscribe (i -> System.out.println (Integer.ToString (i))); Très intéressant, non? Notre observable initial renvoie une chaîne, tandis que l'abonné final reçoit un entier. Bien sûr, l'utilisation de Lambda peut encore simplifier le code:
Observable.Just ("Hello, World!") .Map (S -> S.HashCode ()) .Subscribe (i -> System.out.println (Integer.ToString (i))); Comme mentionné précédemment, moins les choses sont souscrites, mieux c'est. Ajoutons un autre opérateur de carte.
Observable.Just ("Hello, World!") .Map (S -> S.HashCode ()) .map (i -> Integer.ToString (i)) .Subscribe (s -> System.out.println (s)); Pas convaincu?
Pensez-vous que notre exemple est trop simple pour vous convaincre? Vous devez comprendre les deux points suivants:
1. Observable et l'abonné peut tout faire
L'observable peut être une requête de base de données et l'abonné est utilisé pour afficher les résultats de la requête; Observable peut être un événement de clic à l'écran, et l'abonné est utilisé pour répondre aux événements de clic; Observable peut être une demande de réseau et l'abonné est utilisé pour afficher les résultats de la demande.
2. Observable et l'abonné sont indépendants du processus de transformation intermédiaire.
Un nombre de cartes peut être ajoutée ou diminuée entre observable et abonné. L'ensemble du système est fortement combinable et les données de fonctionnement sont un processus très simple.
Exemple
1. Préparation
Supposons que j'ai une méthode comme celle-ci:
Cette méthode renvoie la liste URL d'un site Web basé sur la chaîne d'entrée (AHHA, moteur de recherche)
Observable <list <string>> requête (texte de chaîne);
Maintenant, je veux construire un système robuste qui peut interroger les chaînes et afficher les résultats. Sur la base du contenu du blog précédent, nous pouvons écrire le code suivant:
Query ("Hello, World!") .Subscribe (URLS -> {for (String URL: URLS) {System.out.println (url);}});Bien sûr, ce type de code ne peut pas être toléré, car le code ci-dessus nous a fait perdre la capacité de modifier le flux de données. Une fois que nous voulons changer chaque URL, nous ne pouvons le faire que chez l'abonné. Nous n'avons pas utilisé un opérateur de carte aussi cool ()! ! !
Bien sûr, je peux utiliser l'opérateur de carte. L'entrée de la carte est la liste des URL. Lors du traitement, il doit encore traverser chacun, ce qui est également très douloureux.
Heureusement, il existe également la méthode observable.from (), qui reçoit une collection en entrée, puis publie un élément à l'abonné à la fois:
Observable.from ("URL1", "URL2", "URL3") .Subscribe (URL -> System.out.println (URL)); Utilisons cette méthode sur la scène tout à l'heure:
query ("Hello, World!") .Subscribe (URLS -> {observable.from (URLS) .Subscribe (url -> System.out.println (url));});
Bien que la boucle pour chaque boucle soit supprimée, le code semble toujours désordonné. Les abonnements multiples imbriqués semblent non seulement laids et difficiles à modifier, mais plus sérieusement, il détruira certaines des caractéristiques de Rxjava que nous n'avons pas encore mentionnées.
2. Amélioration
Le Sauveur est là, il est FlatMap ().
Observable.flatmap () reçoit la sortie d'un observable en entrée et sort un autre observable en même temps. Regardez directement le code:
Query ("Hello, World!") .flatMap (new func1 <list <string>, observable <string>> () {@Override public observable <string> appel (list <string> urls) {return observable.from (urls);}}) .subscribe (url -> System.out.println (url)); Ici, j'ai publié l'intégralité du code de fonction pour vous faciliter pour comprendre ce qui se passe. L'utilisation de Lambda peut considérablement simplifier la longueur du code:
query ("Hello, World!") .flatMap (URLS -> observable.from (URLS)) .Subscribe (url -> System.out.println (URL));FlatMap () a-t-il l'air bizarre? Pourquoi retourne-t-il un autre observable? Le point clé pour comprendre FlatMap est que la nouvelle sortie observable de FlatMap est exactement ce que nous voulons recevoir chez l'abonné. Désormais, l'abonné ne reçoit plus List <string>, mais reçoit à la place quelques chaînes uniques de colonnes, tout comme la sortie de observable.from ().
Cette partie est également la partie la plus difficile lorsque j'ai appris pour la première fois rxjava. Une fois que je l'ai soudainement réalisé, de nombreuses questions de Rxjava ont été résolues.
3. Ça peut être mieux
FlatMap () n'est vraiment pas une meilleure idée, il peut renvoyer n'importe quel objet observable qu'il veut retourner.
Par exemple, la méthode suivante:
// Renvoie le titre du site Web, et s'il est 404, retournez Null observable <string> getTitle (URL de chaîne);
Après l'exemple précédent, maintenant je ne veux plus imprimer l'URL, mais imprimez plutôt le titre de chaque site Web que je reçois. Le problème est que ma méthode ne peut passer dans une URL à la fois, et la valeur de retour n'est pas une chaîne, mais un objet observable qui sortira une chaîne. L'utilisation de FlatMap () peut simplement résoudre ce problème.
Query ("Hello, World!") .flAtMap (URLS -> observable.from (URLS)) .flatMap (Nouvel Func1 <String, observable <string >> () {@Override public Observable <string> Call (String URL) {return gettitle (url);}}). subscribe (title -> System.out.PrintLn (title)); 4. Utilisez Lambda:
Query ("Hello, World!") .flatMap (URLS -> observable.from (URLS)) .flatMap (url -> getTitle (url)) .subscribe (title -> System.out.println (title)); Cela ne semble-t-il pas incroyable? Je peux réellement combiner plusieurs méthodes indépendantes pour renvoyer des objets observables ensemble! Très beau!
Plus que cela, j'ai également combiné les appels de deux API dans un appel enchaîné. Nous pouvons lier autant d'appels API autant que possible. Tout le monde doit savoir à quel point il est douloureux de synchroniser tous les appels d'API, puis de combiner les résultats de rappel de tous les appels d'API dans les données à afficher. Ici, nous avons réussi à éviter Hellback Hell (rappels imbriquées multicouches, ce qui rend le code difficile à lire et à maintenir). Maintenant, toute logique est enveloppée dans cet appel réactif simple.
5. Rich Opérateurs <Br /> Jusqu'à présent, nous sommes entrés en contact avec deux opérateurs, et il y a plus d'opérateurs dans RXJAVA, alors comment utilisons-nous d'autres opérateurs pour améliorer notre code?
gettitle () renvoie null si l'URL n'existe pas. Nous ne voulons pas sortir "null", alors nous pouvons filtrer la valeur nul à partir de la liste de titres retournée!
Query ("Hello, World!") .flAtMap (URLS -> observable.from (URLS)) .flatMap (url -> getTitle (url)) .filter (title -> title! = null) .subscribe (title -> System.out.println (title));Filter () produit les mêmes éléments en tant qu'entrée et filtre ceux qui ne répondent pas aux critères de contrôle.
Si nous ne voulons que jusqu'à 5 résultats:
Query ("Hello, World!") .flatMap (URLS -> observable.from (URLS)) .flatMap (url -> getTitle (url)) .filter (title -> title! = null) .take (5) .subscribe (title -> System.out.println (title));TAPT () produit le nombre maximum de résultats.
Si nous voulons enregistrer chaque titre sur le disque avant d'imprimer:
Query ("Hello, World!") .flatMap (URLS -> observable.from (URLS)) .flatMap (url -> gettitle (url)) .filter (title -> title! = null) .take (5) .doonnext (title -> saveTiTle (title)) .subScribe (title -> System.out.PrintLn (title));DoonNext () nous permet de faire des choses supplémentaires avant de sortir un élément à la fois, comme enregistrer le titre ici.
Est-il facile de voir à quel point il est facile de faire fonctionner le flux de données ici? Vous pouvez ajouter autant d'opérations que vous le souhaitez et ne pas gâcher votre code.
Rxjava contient un grand nombre d'opérateurs. Le nombre d'opérateurs est un peu effrayant, mais il vaut la peine d'être vérifié un par un afin que vous puissiez savoir quels opérateurs peuvent être utilisés. Il peut prendre un certain temps pour comprendre ces opérateurs, mais une fois que vous comprenez, vous comprendrez pleinement la puissance de Rxjava.
Vous pouvez même écrire des opérateurs personnalisés! Ce blog n'a pas l'intention de personnaliser l'opérateur. Si vous le souhaitez, veuillez Go Google vous-même.
Comment vous sentez-vous?
Eh bien, vous êtes sceptique et c'est difficile à convaincre, alors pourquoi vous souciez-vous de ces opérateurs?
Parce que les opérateurs vous permettent de faire quoi que ce soit au flux de données.
Lier une série d'opérateurs peut accomplir une logique complexe. Le code est décomposé en une série d'extraits qui peuvent être combinés. Ceci est le charme de la programmation des fonctions réactives. Plus vous l'utilisez, plus vous changerez votre réflexion sur la programmation.
De plus, Rxjava nous permet également de traiter plus facilement les données. Dans le dernier exemple, nous appelons deux API, traitons les données renvoyées par l'API et les enregistrons sur disque. Mais notre abonné ne le sait pas, il pense simplement qu'il reçoit un objet <string> observable. Un bon emballage apporte également la commodité de codage!
Dans la troisième partie, je présenterai d'autres fonctionnalités intéressantes de Rxjava, telles que la gestion des erreurs et la concurrence, qui ne sont pas directement utilisées pour traiter les données.