Je peux le lire! RxJava

Aperçu

Quand je vois pour la première fois la source écrite en RxJava, le flux du processus est difficile à suivre, Il y a de nombreux cas où nous ne pouvons pas comprendre la partie de la logique que nous voulons à l'origine comprendre. (Au moins j'étais ...)

Cet article présente les principales classes et méthodes de RxJava,

En suivant le processus tout en déplaçant réellement le code, Lisez les lecteurs! RxJava ».

Cible

―― Qu'est-ce que RxJava est délicieux?

observable.png

** "Je ne comprends pas la signification de ce chiffre! !! 』** Je te l'enverrai.

Environnement d'exécution

--Java8 (ou supérieur)

Dans le cas de gradle, écrivez simplement ce qui suit.

build.gradle


repositories {
    mavenCentral()
    maven { url 'https://oss.jfrog.org/libs-snapshot' }
}

dependencies {
    compile 'io.reactivex.rxjava2:rxjava:2.2.0-SNAPSHOT'
}

Pour les autres personnes, veuillez vous référer à ce qui suit. https://github.com/ReactiveX/RxJava

De plus, lambda est utilisé comme connaissance préalable. Si vous êtes inquiet à propos de lambda, veuillez en savoir plus sur ce qui suit. https://qiita.com/sanotyan1202/items/64593e8e981e8d6439d3

Exemple de code

Un exemple de code est ci-dessous. Cela fonctionne tel quel, alors essayez-le.

https://github.com/youyanntoto/RxJavaSample

En outre, ce volume expliquera principalement l'exemple de code.

Histoire principale

À propos du contenu de traitement de l'exemple de code

Main.java


    public static void main(String[] args) {
        System.out.println("*** main start ***");

        RestUtil.Weather tokyoWeather = RestUtil.getWeather(RestUtil.Place.TOKYO);
        RestUtil.Weather yokohamaWeather = RestUtil.getWeather(RestUtil.Place.YOKOHAMA);
        RestUtil.Weather nagoyaWeather = RestUtil.getWeather(RestUtil.Place.NAGOYA);

        System.out.println(tokyoWeather);
        System.out.println(yokohamaWeather);
        System.out.println(nagoyaWeather);

        System.out.println("*** main end ***");
    }

RestUtil.java


    public static Weather getWeather(Place place) {
        Weather weather;

        //Obtenez la météo appropriée pour chaque endroit
        switch (place) {
            case TOKYO:
                weather = Weather.SUNNY;
                break;
            case YOKOHAMA:
                weather = Weather.RAINY;
                break;
            case NAGOYA:
                weather = Weather.WINDY;
                break;
            default:
                weather = Weather.SUNNY;
                break;
        }

        try {
            //Temps de traitement de la communication 500~Faites que cela prenne 999 ms
            Thread.sleep(new Random().nextInt(500) + 500);
        } catch (InterruptedException e) {
            // nop
        }

        return weather;
    }

Voir la classe principale. Effectuer une communication de repos (RestUtil # getWeather (RestUtil.Place)) Exécute le processus d'acquisition de la météo (RestUtil.Weather) dans la zone spécifiée.

Comme vous pouvez le voir dans la classe RestUtil, le processus de communication lui-même est un mannequin.

RestUtil.getWeather prend désormais 500 à 999 ms chacun. Donc, si vous exécutez Main.java, cela prendra environ 1500-3000ms de 500-999ms x 3.

Maintenant, réactivons le code ci-dessus.

Partie 1. "Completable" pour indiquer l'achèvement

Exemple de code

CompletableSample.java


    public static void main(String[] args) {
        System.out.println("*** main start ***");

        Completable.create(emitter -> {
            RestUtil.Weather tokyoWeather = RestUtil.getWeather(RestUtil.Place.TOKYO);
            RestUtil.Weather yokohamaWeather = RestUtil.getWeather(RestUtil.Place.YOKOHAMA);
            RestUtil.Weather nagoyaWeather = RestUtil.getWeather(RestUtil.Place.NAGOYA);

            System.out.println(tokyoWeather);
            System.out.println(yokohamaWeather);
            System.out.println(nagoyaWeather);
            emitter.onComplete();

        }).subscribe(() -> {
            System.out.println("Complete!!");

        }, throwable -> {
            System.out.println("Error!!");
            throwable.printStackTrace();

        });

        System.out.println("*** main end ***");
    }

Commentaire

Tout d'abord, le traitement de l'argument de Completable.create (dans le lambda) est exécuté. Le traitement lui-même est le même que le traitement de Main.java au début.

Ensuite, emitter.onComplete () En appelant, le premier argument de subscribe est exécuté.

Au fait, le deuxième argument de subscribe est lorsque vous appelez emitter.onError () Sinon, il sera exécuté lorsqu'une erreur est renvoyée dans le lambda de l'argument de Completable.create. Le jetable qui y est passé sera l'objet d'erreur qui s'est produit en cas d'erreur.

Résumé, Traitement des arguments Completable.create → Souscrire le traitement du 1er argument (onSuccess) ou le traitement du 2ème argument (onError) Le processus est exécuté dans le flux.

Partie 2. "Simple" passant une valeur

Exemple de code

SingleSample.java


    public static void main(String[] args) {
        System.out.println("*** main start ***");

        Single.<List<RestUtil.Weather>>create(emitter -> {
            RestUtil.Weather tokyoWeather = RestUtil.getWeather(RestUtil.Place.TOKYO);
            RestUtil.Weather yokohamaWeather = RestUtil.getWeather(RestUtil.Place.YOKOHAMA);
            RestUtil.Weather nagoyaWeather = RestUtil.getWeather(RestUtil.Place.NAGOYA);
            emitter.onSuccess(List.of(tokyoWeather, yokohamaWeather, nagoyaWeather));

        }).subscribe(weathers -> {
            System.out.println("Complete!!");
            for (RestUtil.Weather weather : weathers) {
                System.out.println(weather);
            }
            
        }, throwable -> {
            System.out.println("Error!!");
            throwable.printStackTrace();
            
        });

        System.out.println("*** main end ***");
    }

Commentaire

Comme le Completable de la partie 1 Gestion des arguments Single.create → Souscrire le traitement du 1er argument (onSuccess) ou le traitement du 2ème argument (onError) Le processus est exécuté dans le flux.

La différence est l'endroit où la météo est sortie.

Dans Single, vous pouvez transmettre ** une seule ** valeur au traitement suivant, donc Lister la météo dans chaque région emitter.onSuccess(T) En appelant, il est passé au traitement du premier argument de subscribe. De plus, le type de l'argument qui y est passé est spécifié par les génériques au moment de Single # create.

Si vous avez traité Promise en JavaScript, l'image est similaire.

Partie 3. (édition supplémentaire) "Stream"

Exemple de code

StreamSample.java


/**
 * sample for Stream
 */
    public static void main(String[] args) {
        System.out.println("*** main start ***");

        RestUtil.Weather tokyoWeather = RestUtil.getWeather(RestUtil.Place.TOKYO);
        RestUtil.Weather yokohamaWeather = RestUtil.getWeather(RestUtil.Place.YOKOHAMA);
        RestUtil.Weather nagoyaWeather = RestUtil.getWeather(RestUtil.Place.NAGOYA);

        Stream.of(List.of(tokyoWeather, yokohamaWeather, nagoyaWeather))
                .forEach(weather -> {
                    System.out.println(weather + "");
                });

        System.out.println("*** main end ***");
    }

Commentaire

Avant de parler d'Observable, apprenons un peu plus sur Stream. Si vous comprenez déjà Stream, ignorez-le.

Ensuite, le flux de traitement, Tout d'abord, obtenez la météo de chaque district et générez une liste, Il est diffusé et la météo de chaque district est sortie.

La forme sous laquelle les valeurs circulent en séquence est similaire à Observable, qui sera expliquée ci-après. Veuillez comprendre le déroulement du processus.

Partie 4. «Observable» qui transmet plusieurs valeurs

Exemple de code

ObservableSample.java


    public static void main(String[] args) {
        System.out.println("*** main start ***");

        Observable.<RestUtil.Weather>create(emitter -> {
            RestUtil.Weather tokyoWeather = RestUtil.getWeather(RestUtil.Place.TOKYO);
            emitter.onNext(tokyoWeather);

            RestUtil.Weather yokohamaWeather = RestUtil.getWeather(RestUtil.Place.YOKOHAMA);
            emitter.onNext(yokohamaWeather);

            RestUtil.Weather nagoyaWeather = RestUtil.getWeather(RestUtil.Place.NAGOYA);
            emitter.onNext(nagoyaWeather);

            emitter.onComplete();

        }).subscribe(weather -> {
            System.out.println("Next!!");
            System.out.println(weather);

        }, throwable -> {
            System.out.println("Error!!");
            throwable.printStackTrace();

        }, () -> {
            System.out.println("Complete!!");

        });

        System.out.println("*** main end ***");
    }

Commentaire

Contrairement à Completable et Single conventionnel, Il y a trois arguments pour s'abonner.

En tant que flux de traitement Le processus Observable.create est exécuté en premier. Après cela, le premier argument de subscribe est exécuté à chaque fois que emitter.onNext (T) est appelé. Enfin, lorsque emitter.onComplete () est appelé, le troisième argument de subscribe est exécuté. Le deuxième argument est le processus qui est appelé lorsqu'une erreur se produit, comme par le passé.

Résumé, Traitement Observable.create → Souscrire le traitement du 1er argument (onNext) ou du 2ème argument (onError) → Traitement du troisième argument (onComplete) de souscription Le processus est exécuté dans le flux.

Observable peut transmettre plusieurs valeurs, de sorte qu'il peut générer la valeur à chaque fois qu'une communication est effectuée.

Partie 5. "subscribeOn", "observeOn" pour spécifier le fil

Exemple de code

ThreadSample.java


    public static void main(String[] args) {
        System.out.println("*** main start ***");

        Observable.<RestUtil.Weather>create(emitter -> {
            RestUtil.Weather tokyoWeather = RestUtil.getWeather(RestUtil.Place.TOKYO);
            emitter.onNext(tokyoWeather);

            RestUtil.Weather yokohamaWeather = RestUtil.getWeather(RestUtil.Place.YOKOHAMA);
            emitter.onNext(yokohamaWeather);

            RestUtil.Weather nagoyaWeather = RestUtil.getWeather(RestUtil.Place.NAGOYA);
            emitter.onNext(nagoyaWeather);

            emitter.onComplete();

        }).subscribeOn(Schedulers.io())
                .observeOn(Schedulers.newThread())
                .subscribe(weather -> {
                    System.out.println("Next!!");
                    System.out.println(weather);

                }, throwable -> {
                    System.out.println("Error!!");
                    throwable.printStackTrace();

                }, () -> {
                    System.out.println("Complete!!");

                });

        System.out.println("*** main end ***");
    }

Commentaire

Dans le code source expliqué dans la partie 4 "subscribeOn", "observeOn" A été ajouté.

Il y a quelques avantages de RxJava, Le plus important est que le processus de spécification de ce fil est facile à écrire.

"subscribeOn" spécifie le thread de traitement dans Observable.create, "observeOn" peut spécifier le thread de traitement dans subscribe.

Dans l'exemple ci-dessus, le traitement de la communication est effectué par le thread IO. Le traitement suivant (traitement qui utilise le résultat de la communication) est exécuté par un autre thread.

En tant que scène souvent utilisée, dans le développement Android, le traitement de la communication est effectué dans un thread séparé, Il est courant que le thread principal effectue le traitement qui gère la vue dans le traitement suivant.

Partie 6. Convertir la valeur "map"

Exemple de code

ObservableMapSample.java


    public static void main(String[] args) {
        System.out.println("*** main start ***");

        Observable.<RestUtil.Weather>create(emitter -> {
            RestUtil.Weather tokyoWeather = RestUtil.getWeather(RestUtil.Place.TOKYO);
            emitter.onNext(tokyoWeather);

            RestUtil.Weather yokohamaWeather = RestUtil.getWeather(RestUtil.Place.YOKOHAMA);
            emitter.onNext(yokohamaWeather);

            RestUtil.Weather nagoyaWeather = RestUtil.getWeather(RestUtil.Place.NAGOYA);
            emitter.onNext(nagoyaWeather);

            emitter.onComplete();

        }).map(weather -> {
            switch (weather) {
                case SUNNY:
                    return "happy day!!";
                case RAINY:
                    return "sad day...";
                case WINDY:
                default:
                    return "normal day";
            }

        }).subscribe(weather -> {
            System.out.println("Next!!");
            System.out.println(weather);

        }, throwable -> {
            System.out.println("Error!!");
            throwable.printStackTrace();

        }, () -> {
            System.out.println("Complete!!");

        });

        System.out.println("*** main end ***");
    }

Commentaire

Une nouvelle carte de méthode a été ajoutée au code source de la partie 4. Vous pouvez voir que vous pouvez réellement le déplacer, La valeur passée au premier argument de subscribe a été ** convertie **.

Comme vous pouvez le voir, ce qui est converti est le processus passé à la carte.

La carte reçoit la valeur qui coule et renvoie la valeur convertie dans la clause de retour. Vous pouvez convertir la valeur à envoyer au traitement suivant.

Partie 7. Connectez "flatMap"

Exemple de code

ObservableFlatMapSample.java


    public static void main(String[] args) {
        System.out.println("*** main start ***");

        Observable.<RestUtil.Place>create(emitter -> {
            emitter.onNext(RestUtil.Place.TOKYO);
            emitter.onNext(RestUtil.Place.YOKOHAMA);
            emitter.onNext(RestUtil.Place.NAGOYA);
            emitter.onComplete();

        }).flatMap(place -> {
            return Observable.create(emitter -> {
                RestUtil.Weather tokyoWeather = RestUtil.getWeather(place);
                emitter.onNext(tokyoWeather);
                emitter.onComplete();
            });

        }).subscribe(weather -> {
            System.out.println("Next!!");
            System.out.println(weather);

        }, throwable -> {
            System.out.println("Error!!");
            throwable.printStackTrace();

        }, () -> {
            System.out.println("Complete!!");

        });

        System.out.println("*** main end ***");
    }

Commentaire

Une nouvelle méthode flatMap a été ajoutée au code source de la partie 4. La valeur transmise dans le premier Observable.create a changé de météo en région. Et un autre Observable est généré dans flatMap.

Le flux de traitement est Le premier processus Observable est exécuté, Chaque fois que emitter.onNext (T) est appelé Le traitement dans le deuxième Observable qui est retourné dans le flatMap est effectué. En d'autres termes, flatMap relie le premier Observable et le second Observable.

Dans cet exemple, le point de communication n'est que le deuxième observable, il n'y a donc pas de goût particulier, mais En fait, le traitement DB est effectué avec le premier Observable, Le traitement de la communication est effectué avec le deuxième Observable Il est utilisé dans les scènes où un traitement long et long est effectué.

À la fin

Avec ce qui précède, "Lisez! RxJava »est terminé.

Parce que le monde de RxJava est vaste et toujours en croissance Le contenu de cet article ne suffit pas à tout couvrir, Vous devriez être capable de comprendre les bases en combinant et en appliquant les classes et les méthodes présentées ici. (Au moins dans le sens d'être lisible)

J'espère pouvoir aider tous ceux qui vont se lancer dans le monde de RxJava.

Recommended Posts

Je peux le lire! RxJava
Je veux utiliser NetBeans sur Mac → Je peux l'utiliser!
Je le posterai légèrement
J'ai lu module-info.java dans java.base
J'ai lu le livre de démarrage de Kotlin
J'ai essayé node-jt400 (lecture IFS)
J'ai lu la source de ArrayList que j'ai lu
J'ai lu la source d'Integer
J'ai lu la source de Long
Pouvez-vous le faire? Java EE
J'ai lu la source de Short
J'ai lu la source de Byte
J'ai lu la source de String
Heroku peut être déployé, mais j'obtiens une erreur et je ne peux pas l'ouvrir
Je ne peux pas utiliser SQS qui peut lire le questionnaire avec un scanner → Je pourrais l'utiliser après avoir changé le ver java