5 Reasons to Love RxJava

Reactive Extensions (Rx) est un ensemble de méthodes et d’interfaces qui offrent des moyens rapides, faciles à maintenir et à comprendre pour résoudre les problèmes des développeurs Java. Vous l’avez bien compris, Rx est un ensemble d’outils pour vous aider à écrire un code élégant mais plus simple.

Dans le cas de Java, l’ajout de la bibliothèque Rx vous permet d’orchestrer plusieurs actions qui se produisent en raison de certains événements dans le système. De plus, cela élimine la douleur d’utiliser des callbacks et une gestion d’état globale horriblement complexe.

Lorsque vous commencez à travailler avec RxJava, vous pourriez penser que c’est trop difficile à comprendre et que cet ensemble de nouveaux outils n’aidera pas beaucoup. Mais avec le temps, vous apprendrez les nombreux avantages qu’offre RX :

Intuitivité — La description des actions dans Rx utilise le même style que dans la programmation fonctionnelle, par exemple, les flux Java (Java Streams). Si vous travaillez avec Rx, cela vous donne la possibilité d’utiliser des transformations fonctionnelles sur des flux d’événements.

Extensibilité — RxJava peut être étendu par des opérateurs personnalisés.

Déclarativité — Les transformations fonctionnelles sont annoncées de manière déclarative.

Composabilité — Les opérateurs dans RxJava s’assemblent facilement pour réaliser des opérations complexes.

Convertibilité — Les opérateurs dans RxJava peuvent transformer les types de données en filtrant, traitant et développant des flux de données.

Rx est basé sur le modèle Observer. Les éléments clés sont l’Observer et le Subscriber. Observable est le type de base. Cette classe contient la partie principale de l’implémentation de Rx et inclut tous les opérateurs de base.

Alors, pourquoi RxJava ?

1. Flux asynchrones
2. Approche fonctionnelle
3. Mise en cache simplifiée
4. Opérateurs avec Schedulers
5. Utilisation de Subjects

1. Flux asynchrones

Prenons un exemple :

Vous devez envoyer une requête à la base de données, puis une fois qu’elle est terminée, vous devez immédiatement commencer à récupérer à la fois les messages et les paramètres. Une fois le travail terminé, vous devez afficher un message de bienvenue.

Si nous voulons faire la même chose en Java SE et Android, nous devons suivre les étapes suivantes :

  1. Exécuter 3-4 AsyncTasks différents ;
  2. Créer un sémaphore qui attend la fin des deux requêtes (paramètres et messages) ;
  3. Créer des champs au niveau des objets pour stocker les résultats.

Nous pouvons minimiser toutes ces opérations en travaillant avec RxJava. Dans ce cas, le code ressemble à un thread qui est situé à un seul endroit et construit sur la base d’un paradigme fonctionnel.

Alternativement, nous pouvons utiliser la liaison optionnelle :

Observable.fromCallable(createNewUser())
  .subscribeOn(Schedulers.io())
  .flatMap(new Func1<User, Observable<Pair<Settings, List>>>() {
      //  travaille avec les paramètres
  })
  .doOnNext(new Action1<Pair<Settings, List>>() {
      @Override
      public void call(Pair<Settings, List> pair) {
          System.out.println("Paramètres reçus" + pair.first);
      }
  })
  .flatMap(new Func1<Pair<Settings, List>, Observable>() {
      // travaille avec les messages
  })
  .subscribe(new Action1() {
      @Override
      public void call(Message message) {
          System.out.println("Nouveau message " + message);
      }
  });

2. Approche fonctionnelle

Si vous êtes familier avec la programmation fonctionnelle, comme les concepts de map et zip, travailler avec RxJava vous sera beaucoup plus facile. Nous pouvons dire que la programmation fonctionnelle est l’utilisation active de fonctions comme paramètres et résultats dans d’autres fonctions. Par exemple, map est une fonction d’ordre supérieur, utilisée dans de nombreux langages de programmation. Elle applique cette fonction à chaque élément d’une liste, renvoyant une liste de résultats. Voici à quoi cela ressemble :

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) {
              // cette exception fait partie de rx-java
              throw OnErrorThrowable.addValueAsLastCause(e, file);
          }
      }
  });

 

3. Mise en cache simplifiée

Le prochain extrait de code utilise la méthode de mise en cache de telle sorte qu’une seule copie enregistre le résultat après qu’il ait été réussi pour la première fois.

Single < List < Todo >> todosSingle = Single.create(emitter - > {
      Thread thread = new Thread(() - > {
          try {
              List < Todo > todosFromWeb = // interroger un service web
              System.out.println("Je ne suis appelé qu'une seule fois!");
              emitter.onSuccess(todosFromWeb);
          } catch (Exception e) {
              emitter.onError(e);
          }
      });
      thread.start();
  });

  // mettre en cache le résultat du single, de sorte que la requête web ne soit effectuée qu'une seule fois
  Single < List < Todo >> cachedSingle = todosSingle.cache();

4. Opérateurs avec Schedulers

Il existe une variété d’opérateurs qui nécessitent de spécifier un Scheduler pour fonctionner. En même temps, ils ont leurs méthodes surchargées qui utilisent computation(), delay() comme Scheduler. Voici l’exemple :

TestSubscriber subscriber = new TestSubscriber<>();
  Observable.just(1).delay(1, TimeUnit.SECONDS).subscribe(subscriber);
  subscriber.awaitTerminalEvent();
  Logger.d("LastSeenThread: " + subscriber.getLastSeenThread().getName());

Nous pouvons voir le résultat suivant malgré le fait que nous n’ayons indiqué aucun Scheduler.
Malgré le fait que nous n’ayons indiqué aucun Scheduler, le résultat sera le suivant :

LastSeenThread: RxComputationThreadPool-1

Si vous souhaitez éviter d’utiliser le scheduler de calcul, vous devez indiquer les schedulers requis comme 3ème argument.

.delay(1, TimeUnit.SECONDS, Schedulers.immediate())

Outre delay(), il existe de nombreux autres opérateurs qui peuvent changer de Scheduler : interval(), timer(), surcharges de buffer(), debounce(), skip(), take(), timeout(), etc.

5. Utilisation de Subjects

En travaillant avec des Objets, vous devez tenir compte du fait que, par défaut, la séquence des changements de données envoyés à onNext subject sera exécutée (implémentée) dans le même thread qui a été utilisé pour appeler la méthode onNext(), jusqu’à ce que l’opérateur observeOn() apparaisse dans cette séquence.

observeOn et subscribeOn sont mentionnés ici, mais le résultat sera le suivant :

doOnNext: RxCachedThreadScheduler-1onNext: RxNewThreadScheduler-1doOnNext: mainonNext: RxNewThreadScheduler-1

Cela signifie que lorsque nous nous abonnons à subject, il renvoie la valeur immédiatement, puis elle est traitée dans un thread de Shedulers.io(). Et ensuite, lorsque le message suivant arrive à subject, nous utilisons le thread où onNext() a été appelé.

Conclusion

L’utilisation de Rx nous aide à résoudre les problèmes suivants :

  • Résoudre facilement le problème de la mise en cache (sans créer de classes de mise en cache) ;
  • Se débarrasser de l’AsyncTask standard, combiner les requêtes et traiter les résultats pendant leur réception ;
  • Fuite de mémoire réduite de 90 % ;
  • Réduire la quantité de lignes de code et augmenter la réactivité d’une application. Il n’est pas nécessaire d’écrire de nombreuses AsyncTask différentes, RxJava permet de combiner les méthodes sans problèmes.

Comme vous pouvez le constater, RxJava est un outil nouveau et vraiment performant pour travailler avec les requêtes réseau et les threads, pour traiter les réponses et pour prévenir les fuites de mémoire.

À propos de Redwerk

Depuis 2005, Redwerk fournit des services de programmation externalisée pour un large éventail d’industries telles que le E-commerce, l’automatisation des entreprises, la santé électronique, les médias et divertissement, le E-government, le développement de jeux, et bien sûr, pour les Startups et l’innovation. Notre équipe de développeurs offshore dédiés avec leur expérience abondante trouve toujours les meilleures solutions techniques pour les projets de toutes tailles. Redwerk s’engage dans le développement d’applications iOS et Android personnalisées à partir de zéro. Nous respectons le temps de nos clients, par conséquent, nous respectons toujours les délais.