Considérez RxJava comme une bibliothèque qui facilite l'écriture du traitement asynchrone

RxJava Advent Calendar 2017 Hier, c'était "[Autorisation d'exécution de processus avec RxPermissions] de @ toastkidjp](https://qiita.com/toastkidjp/items/3620a037aa7f72bec8b4)". Le troisième jour est le "[RxAndroid and RxSwing Scheduler] de @ guignol (https://qiita.com/guignol/items/98089adfa01b571c9c94)". Une histoire intéressante sur la mise en œuvre de Scheduler.

Personne ne courait pour le deuxième jour, donc ça faisait déjà un moment, mais je vais écrire un article.

Aperçu

Savoir «à quoi cela sert-il?» Améliorera votre motivation lorsque vous étudiez. J'ai pensé qu'il pourrait y avoir un moyen de commencer à étudier après avoir su "Quel type de bibliothèque RxJava peut-il faire?", J'ai donc créé RxJava "traitement asynchrone". Pensons-y comme une bibliothèque Java qui facilite l'écriture.

Cible

Les personnes intéressées par RxJava mais qui ne l'ont pas encore utilisé (en particulier les développeurs d'applications Android)

Non couvert dans cet article

Quoi écrire dans cet article

Description de RxJava en tant que bibliothèque facilitant l'écriture du traitement asynchrone

Remarquer

--Utiliser l'expression Lambda


Qu'est-ce qui différencie RxJava des traditionnels?


introduction

RxJava est fourni sous forme de bibliothèque et peut être installé à l'aide de Maven ou Gradle.

Exigences

Il doit s'agir de la version suivante ou ultérieure.

Name Version
Java 1.6-
Android 2.3-

RxJava est souvent utilisé dans le développement d'applications Android, mais il n'est pas limité à Android et peut être utilisé dans les applications Java et Kotlin classiques.

Notez que RxJava2 a sa propre définition de l'interface fonctionnelle requise, donc Java 8 ou version ultérieure Interface de type de fonction du package java.util.function (Function, Consumer Etc.) et ne sont pas compatibles avec eux.

Ajouter une dépendance

Ajoutez simplement une ligne à build.gradle. Au moment de la rédaction de cet article, 2.1.7 était le dernier.

app/build.gradle


dependencies {
    implementation 'io.reactivex.rxjava2:rxjava:2.1.7'

Pour le développement d'applications Android, il est utile d'ajouter une autre ligne, RxAndroid. Au contraire, cela n'a pas beaucoup de sens d'inclure RxJava sans lui. Le but principal est d'utiliser Scheduler (pour spécifier le thread d'exécution du processus) pour exécuter le processus dans le thread principal d'Android. La dernière version est 2.0.1.

app/build.gradle


    implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'

Si vous souhaitez utiliser des expressions Lambda, vous devez installer Retrolambda ou Android Gradle Plugin 3.0, mais nous les omettreons ici.

Licence

RxJava et RxAndroid Il est sous licence Apache License 2.0. Si vous souhaitez l'utiliser, vous devez écrire la licence dans l'application. Pour les applications Android, com.google.gms: oss-licenses peut vous aider.

Afficher les licences Open Source à l'aide de com.google.gms: oss-licenses


recette

Je me suis demandé s'il n'y avait pas beaucoup d'articles qui utilisent Single (notifier une valeur ou un achèvement ou une erreur) et Completable (notifier l'achèvement ou l'erreur) dans l'article d'introduction de RxJava, je vais donc présenter un exemple utilisant les deux. Faire. Je pense que la désynchronisation des traitements à un niveau fin, qui est la spécialité de RxJava, peut être réalisée principalement en utilisant Single / Maybe / Completable, et je les utilise souvent en développement réel.

Rendre la méthode des goulots d'étranglement asynchrone

ExecutorService Il peut être écrit comme ceci lors du traitement à l'aide du service ExecutorService conventionnel.

Rendre la méthode des goulots d'étranglement asynchrone


final ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(() -> bottleneckMethod());
executor.shutdown();

RxJava Ceci est écrit dans RxJava comme suit.

Rendre la méthode des goulots d'étranglement asynchrone(RxJava)


Completable.fromAction(() -> bottleneckMethod())
    .subscribeOn(Schedulers.newThread())
    .subscribe();

Flux de processus

  1. Exécutez bottleneckMethod () que vous souhaitez traiter de manière asynchrone Action (Fonction qui fonctionne sans argument et sans valeur de retour Obtenir une instance de Completable avec l'interface de type) comme argument
  2. Spécifiez le thread d'exécution avec subscribeOn
  3. Exécutez le processus avec subscribe …… Jusqu'à ce que cette méthode soit appelée, le processus ci-dessus ne sera pas exécuté du tout (exécution retardée)

subscribeOn est une méthode qui spécifie le thread d'exécution pour toute la série de processus. Dans le code ci-dessus, il est spécifié qu'un nouveau thread est créé et le traitement y est exécuté.

Exécution retardée

La fonctionnalité de RxJava est qu'aucun traitement n'est exécuté tant que subscribe () n'est pas appelé. Par exemple, dans le cas du code suivant

Completable completable = Completable.fromAction(() -> bottleneckMethod())
                .subscribeOn(Schedulers.newThread());
System.out.println("start");
completable.subscribe();

Le résultat de l'exécution est le suivant.

Résultat d'exécution


start
RxNewThreadScheduler-1 bottle neck
end.

Le résultat de la méthode println exécutée avant subscribe () est d'abord sorti sur la sortie standard.

Utiliser le résultat du traitement asynchrone

ExecutorService Écrivons de la même manière avec l'API traditionnelle.

Utiliser le résultat du traitement asynchrone(ExecutorService)


final ExecutorService executor = Executors.newSingleThreadExecutor();
final Future awaitable = executor.submit(() -> anyReturnBottleneckMethod());
executor.shutdown();

try {
    System.out.println(awaitable.get(2, TimeUnit.SECONDS));
} catch (InterruptedException e) {
    e.printStackTrace();
} catch (TimeoutException e) {
    e.printStackTrace();
} catch (ExecutionException e) {
    e.printStackTrace();
}

RxJava Le même processus est écrit en utilisant RxJava comme suit.

Utiliser le résultat du traitement asynchrone(RxJava)


Single.create(emitter -> emitter.onSuccess(anyReturnBottleneckMethod()))
    .subscribeOn(Schedulers.newThread())
    .subscribe(System.out::println, Throwable::printStackTrace);

Puisque nous devons utiliser le résultat du traitement, nous utilisons Single pour notifier la valeur. Il est possible de définir le traitement lorsqu'une erreur survient dans le deuxième argument de la méthode subscribe.

En passant, vous pouvez également écrire en utilisant fromCallable au lieu de create. Callable est java.util.concurrent.Callable. Identique à Supplier ajouté dans Java 8 et un type de fonction qui retarde la valeur. Dans l'interface, il a été ajouté en Java 1.5, il semble donc qu'il ait été détourné. En revanche, je ne suis pas sûr car Runnable n'est pas utilisé et une interface fonctionnelle appelée Action est définie séparément.

fromCallable


Single.fromCallable(() -> anyReturnBottleneckMethod())

RxJava peut vous aider lorsque vous souhaitez écrire ce type de code d'attente de traitement asynchrone.

L'important est d'utiliser les bons outils pour le problème que vous souhaitez résoudre. ExecutorService est une bonne API pour écrire du code qui exécute de grandes tâches en parallèle, et il est possible que vous ne puissiez pas attendre un traitement comme celui-ci, mais vous n'êtes pas doué pour cela.

Mettre à jour l'interface utilisateur avec les résultats de la communication réseau

Par exemple, si vous souhaitez exécuter networkRequest () dans un thread d'E / S et afficher le résultat dans TextView, vous pouvez écrire comme suit.

Mettre à jour l'interface utilisateur avec les résultats de la communication réseau


Single.create(emitter -> networkRequest())
      .subscribeOn(Schedulers.io())
      .observeOn(AndroidSchedulers.mainThread())
      .subscribe(textView::setText)

subscribeOn et observeOn

Les deux sont des méthodes pour spécifier le thread d'exécution du traitement. observeOn modifie le thread d'exécution à partir de la méthode suivante. La spécification dans observeOn a priorité sur la spécification dans subscribeOn.

Dans le code précédent, le thread d'exécution change comme suit.

Mettre à jour l'interface utilisateur avec les résultats de la communication réseau


Single.create(emitter -> networkRequest()) // I/O fil
      .subscribeOn(Schedulers.io())
      .observeOn(AndroidSchedulers.mainThread())
      .subscribe(textView::setText)        //Fil principal

Qu'est-ce qui vous rend heureux?

Vous pourriez le penser.

Important sur Android, il existe des restrictions telles que "la communication réseau doit être dans le thread d'arrière-plan" et "la mise à jour de la vue doit être dans le thread principal", et si vous ne le respectez pas, une exception d'exécution se produira et l'application plantera Je vais. Il existe différents mécanismes tels que Handler & Looper pour éviter la restriction. Vous pouvez faire la même chose avec eux, mais avec RxJava (et RxAndroid), vous pouvez écrire du code plus simple.


Éléments à considérer avant la mise en œuvre

  1. Coût d'apprentissage
  2. Nombre de méthodes

1. Coût d'apprentissage

Vous n'avez pas besoin d'étudier autant parce que vous avez seulement besoin de connaître Stream API + α pour l'utiliser pour l'écriture, mais c'est simplement une bibliothèque assez énorme, il faudra donc beaucoup de temps pour la comprendre pleinement. Bien que ce ne soit pas Android, j'ai entendu dire que l'entreprise avait choisi ce dernier parce que le coût d'apprentissage de Rx était devenu un goulot d'étranglement en pesant le coût d'apprentissage de RxSwift + le coût d'introduction de MVVM et le coût d'introduction de Clean Architecture. Il semble que l'implémentation de la série Rx dans chaque langue soit similaire, il peut donc être avantageux pour les développeurs qui utilisaient dans d'autres langues d'entrer en douceur, mais au contraire, il sera difficile pour les personnes qui ne connaissent pas Rx d'entrer. Vous devez également y penser.

2. Nombre de méthodes

L'intégration de RxJava2 dans votre application Android à partir de la fin de 2017 augmentera le nombre de méthodes d'un peu moins de 10000. Ce n'est pas un petit nombre, et selon le projet, il peut dépasser la limite et vous pouvez être obligé de le rendre MultiDex. En fait, c'est le cas des applications que je développe au travail. Une fois installé, il peut être difficile à supprimer (car c'est trop pratique), vous devriez donc également envisager des alternatives. Si vous utilisez Kotlin, assurez-vous de vérifier Coroutine (même si je ne l'ai pas du tout vérifié).


en conclusion

J'ai présenté RxJava comme "une bibliothèque qui rend le traitement asynchrone plus facile à écrire". RxJava, qui vous permet de spécifier le thread d'exécution en petites unités, est largement accepté par les développeurs d'applications Android qui ont des restrictions sur le thread d'exécution dans le framework.

L'important est d'utiliser les bons outils pour le problème que vous souhaitez résoudre. ExecutorService est un outil pour exécuter de gros processus en parallèle, et RxJava est relativement approprié pour la désynchronisation dans de petites unités comme discuté ici.

référence

Livres

"Programmation réactive RxJava" (Shoyusha) …… Cela fait un moment depuis sa sortie, mais à ce stade C'est le livre le plus détaillé et le plus facile à comprendre écrit en japonais.

Lien

Recommended Posts

Considérez RxJava comme une bibliothèque qui facilite l'écriture du traitement asynchrone
Création d'une bibliothèque qui facilite la gestion des préférences partagées Android
Présentation de Spring Boot Actuator, une fonctionnalité qui facilite l'utilisation des applications Spring Boot
[Java] Je souhaite écrire un traitement asynchrone à l'aide de Promise dans Java-Trial of Promise-like syntax of JavaScript-
Comment installer la bibliothèque JavaScript "select2" qui rend les sélections multiples de selectbox à la mode dans Rails 6.0
[1er] RSpec débutant a essayé d'écrire ModelSpec en tant que débutant
Une collection de modèles dont vous voulez être conscient pour ne pas compliquer le code
Traitement inutile des collections - je veux vous donner une chance d'écrire du bon code. 5 [Exemple de refactoring C #]
J'ai créé une action GitHub qui facilite la compréhension du résultat de l'exécution de RSpec