Stellen Sie sich RxJava als eine Bibliothek vor, die das Schreiben von asynchroner Verarbeitung erleichtert

RxJava Advent Calendar 2017 Gestern war @ toastkidjps "Laufzeitberechtigung mit RxPermissions verarbeiten". Der dritte Tag ist @ guignols "RxAndroid and RxSwing Scheduler". Eine interessante Geschichte über die Implementierung von Scheduler.

Am zweiten Tag lief niemand, also ist es schon eine Weile her, aber ich werde einen Artikel schreiben.

Überblick

Zu wissen, wofür das nützlich ist, verbessert Ihre Motivation beim Lernen. Ich dachte, es könnte eine Möglichkeit geben, mit dem Lernen zu beginnen, nachdem ich wusste, welche Art von Bibliothek RxJava kann? ", Also machte ich RxJava zur" asynchronen Verarbeitung ". Stellen wir uns das als eine Java-Bibliothek vor, die das Schreiben erleichtert.

Ziel

Personen, die an RxJava interessiert sind, es aber noch nicht verwendet haben (insbesondere Android-App-Entwickler)

In diesem Artikel nicht behandelt

Was in diesem Artikel zu schreiben

Beschreibung von RxJava als Bibliothek, die das Schreiben von asynchroner Verarbeitung erleichtert

Beachten


Was unterscheidet RxJava von herkömmlichen?


Einführung

RxJava wird als Bibliothek bereitgestellt und kann mit Maven oder Gradle installiert werden.

Bedarf

Es muss die folgende Version oder höher sein.

Name Version
Java 1.6-
Android 2.3-

RxJava wird häufig in der Entwicklung von Android-Apps verwendet, ist jedoch nicht auf Android beschränkt und kann in regulären Java- und Kotlin-Anwendungen verwendet werden.

Beachten Sie, dass RxJava2 eine eigene Definition der erforderlichen Funktionsschnittstelle hat, also Java 8 oder höher Funktionstyp-Schnittstelle des Pakets java.util.function (Funktion, Verbraucher Usw.) und sind nicht mit ihnen kompatibel.

Abhängigkeit hinzufügen

Fügen Sie einfach eine Zeile zu build.gradle hinzu. Zum Zeitpunkt des Schreibens dieses Artikels war 2.1.7 das neueste.

app/build.gradle


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

Für die Entwicklung von Android-Apps ist es hilfreich, eine weitere Zeile hinzuzufügen, RxAndroid. Vielmehr macht es wenig Sinn, RxJava ohne es einzuschließen. Der Hauptzweck besteht darin, Scheduler zu verwenden (um den Ausführungsthread des Prozesses anzugeben), um den Prozess im Hauptthread von Android auszuführen. Die neueste Version ist 2.0.1.

app/build.gradle


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

Wenn Sie Lambda-Ausdrücke verwenden möchten, müssen Sie Retrolambda oder Android Gradle Plugin 3.0 installieren, aber wir werden sie hier weglassen.

Lizenz

Sowohl RxJava als auch RxAndroid Es ist unter Apache License 2.0 lizenziert. Wenn Sie es verwenden möchten, müssen Sie die Lizenz in die App schreiben. Für Android-Apps kann com.google.gms: oss-licenses hilfreich sein.

Anzeigen von Open Source-Lizenzen mit com.google.gms: oss-licenses


Rezept

Ich habe mich gefragt, ob es im RxJava-Einführungsartikel nicht viele Artikel gibt, die Single (einen Wert oder Abschluss oder Fehler benachrichtigen) und Completable (Abschluss oder Fehler benachrichtigen) verwenden. Daher werde ich ein Beispiel mit beiden vorstellen. Machen. Ich denke, dass die Desynchronisation der Verarbeitung auf feiner Ebene, die die Spezialität von RxJava ist, hauptsächlich durch die Verwendung von Single / Maybe / Completable realisiert werden kann, und ich verwende sie häufig in der tatsächlichen Entwicklung.

Machen Sie die Engpassmethode asynchron

ExecutorService Dies kann bei der Verarbeitung mit dem herkömmlichen ExecutorService so geschrieben werden.

Machen Sie die Engpassmethode asynchron


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

RxJava Dies ist in RxJava wie folgt geschrieben.

Machen Sie die Engpassmethode asynchron(RxJava)


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

Prozessablauf

  1. Führen Sie die Engpassmethode () aus, die Sie asynchron verarbeiten möchten Aktion (Funktion, die ohne Argument und ohne Rückgabewert arbeitet Holen Sie sich eine Instanz von Completable with type interface) als Argument
  2. Geben Sie den Ausführungsthread mit subscribeOn an
  3. Führen Sie den Prozess mit subscribe aus. Bis diese Methode aufgerufen wird, wird der obige Prozess überhaupt nicht ausgeführt (verzögerte Ausführung).

subscribeOn ist eine Methode, die den Ausführungsthread für die gesamte Reihe von Prozessen angibt. Im obigen Code wird angegeben, dass ein neuer Thread erstellt und die Verarbeitung dort ausgeführt wird.

Verzögerte Ausführung

Die Funktion von RxJava ist, dass keine Verarbeitung ausgeführt wird, bis subscribe () aufgerufen wird. Zum Beispiel im Fall des folgenden Codes

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

Das Ausführungsergebnis ist wie folgt.

Ausführungsergebnis


start
RxNewThreadScheduler-1 bottle neck
end.

Das Ergebnis der println-Methode, die vor subscribe () ausgeführt wurde, wird zuerst in die Standardausgabe ausgegeben.

Verwenden Sie das Ergebnis der asynchronen Verarbeitung

ExecutorService Schreiben wir auf die gleiche Weise mit der traditionellen API.

Verwenden Sie das Ergebnis der asynchronen Verarbeitung(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 Der gleiche Prozess wird mit RxJava wie folgt geschrieben.

Verwenden Sie das Ergebnis der asynchronen Verarbeitung(RxJava)


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

Da wir das Verarbeitungsergebnis verwenden müssen, verwenden wir Single, um den Wert zu benachrichtigen. Es ist möglich, die Verarbeitung zu definieren, wenn im zweiten Argument der Subscribe-Methode ein Fehler auftritt.

Übrigens können Sie auch mit fromCallable schreiben, anstatt zu erstellen. Aufrufbar ist java.util.concurrent.Callable. Entspricht Lieferant, der in Java 8 hinzugefügt wurde, und einem Funktionstyp, der den Wert verzögert. In der Benutzeroberfläche wurde es in Java 1.5 hinzugefügt, sodass es anscheinend umgeleitet wurde. Andererseits bin ich mir nicht sicher, da Runnable nicht verwendet wird und eine Funktionsschnittstelle namens Action separat definiert wird.

fromCallable


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

RxJava kann Ihnen helfen, wenn Sie diese Art von Wartecode für die asynchrone Verarbeitung schreiben möchten.

Wichtig ist, dass Sie die richtigen Tools für das Problem verwenden, das Sie lösen möchten. ExecutorService ist eine gute API zum Schreiben von Code, der große Aufgaben parallel ausführt, und es ist möglich, dass Sie nicht auf eine solche Verarbeitung warten können, aber nicht gut darin sind.

Aktualisieren Sie die Benutzeroberfläche mit den Ergebnissen der Netzwerkkommunikation

Wenn Sie beispielsweise networkRequest () in einem E / A-Thread ausführen und das Ergebnis in TextView anzeigen möchten, können Sie wie folgt schreiben.

Aktualisieren Sie die Benutzeroberfläche mit den Ergebnissen der Netzwerkkommunikation


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

abonnieren und beobachten

Beides sind Methoden zum Festlegen des Ausführungsthreads der Verarbeitung. watchOn ändert den Ausführungsthread von der folgenden Methode. Die Spezifikation in watchOn hat Vorrang vor der Spezifikation in subscribeOn.

Im vorherigen Code ändert sich der Ausführungsthread wie folgt.

Aktualisieren Sie die Benutzeroberfläche mit den Ergebnissen der Netzwerkkommunikation


Single.create(emitter -> networkRequest()) // I/O Faden
      .subscribeOn(Schedulers.io())
      .observeOn(AndroidSchedulers.mainThread())
      .subscribe(textView::setText)        //Haupt-Bedroung

Was freut dich daran?

Sie könnten so denken.

Unter Android ist es wichtig, dass es Einschränkungen gibt, z. B. "Netzwerkkommunikation muss im Hintergrund-Thread sein" und "Update anzeigen muss im Haupt-Thread sein". Wenn Sie dagegen verstoßen, tritt eine Laufzeitausnahme auf und die App stürzt ab. Ich werde. Es gibt verschiedene Mechanismen wie Handler & Looper, um die Einschränkung zu vermeiden. Sie können dasselbe mit ihnen tun, aber mit RxJava (und RxAndroid) können Sie einfacheren Code schreiben.


Dinge, die vor der Implementierung zu beachten sind

  1. Lernkosten
  2. Anzahl der Methoden

1. Lernkosten

Sie müssen nicht so viel lernen, weil Sie nur Stream API + α kennen müssen, um es zum Schreiben zu verwenden, aber es ist einfach eine ziemlich große Bibliothek, so dass es eine beträchtliche Zeit in Anspruch nehmen wird, sie vollständig zu verstehen. Obwohl es sich nicht um Android handelt, habe ich gehört, dass sich das Unternehmen für Letzteres entschieden hat, da die Lernkosten von Rx zu einem Engpass wurden, indem die Lernkosten von RxSwift + die Einführungskosten von MVVM und die Einführungskosten von Clean Architecture abgewogen wurden. Es scheint, dass die Implementierung von Rx-Serien in jeder Sprache ähnlich ist. Daher kann es für Entwickler, die in anderen Sprachen arbeiten, von Vorteil sein, reibungslos einzutreten. Im Gegenteil, es wird für Personen, die Rx noch nicht kennen, schwierig sein, daran teilzunehmen Sie müssen auch darüber nachdenken.

2. Anzahl der Methoden

Wenn Sie RxJava2 ab Ende 2017 in Ihre Android-App integrieren, erhöht sich die Anzahl der Methoden um knapp 10.000. Es ist keine kleine Zahl, und je nach Projekt kann es das Limit überschreiten und Sie können gezwungen sein, es MultiDex zu machen. Tatsächlich ist dies bei den Apps der Fall, die ich bei der Arbeit entwickle. Einmal installiert, kann es schwierig sein, es zu entfernen (zu viel für die Bequemlichkeit), daher sollten Sie auch Alternativen in Betracht ziehen. Wenn Sie Kotlin verwenden, stellen Sie sicher, dass Sie Coroutine überprüfen (obwohl ich es überhaupt nicht überprüft habe).


abschließend

Ich habe RxJava als "eine Bibliothek eingeführt, die das Schreiben von asynchroner Verarbeitung erleichtert". RxJava, mit dem Sie den Ausführungsthread in kleinen Einheiten angeben können, wird von Android-App-Entwicklern, die Einschränkungen für den Ausführungsthread im Framework haben, weitgehend akzeptiert.

Wichtig ist, dass Sie die richtigen Tools für das Problem verwenden, das Sie lösen möchten. ExecutorService ist ein Tool zum parallelen Ausführen großer Prozesse, und RxJava eignet sich relativ gut für die Desynchronisation in kleinen Einheiten, wie hier erläutert.

Referenz

Bücher

"RxJava Reactive Programming" (Shoyusha) ... Es ist eine Weile her, seit es veröffentlicht wurde, aber zu diesem Zeitpunkt Es ist das detaillierteste und leicht verständliche Buch in japanischer Sprache.

Verknüpfung

Recommended Posts

Stellen Sie sich RxJava als eine Bibliothek vor, die das Schreiben von asynchroner Verarbeitung erleichtert
Erstellt eine Bibliothek, die die Handhabung von freigegebenen Android-Einstellungen erleichtert
Einführung des Spring Boot Actuator, einer Funktion, die die Bedienung von Spring Boot-Anwendungen erleichtert
[Java] Ich möchte eine asynchrone Verarbeitung mit Promise in der Java-Testversion der Promise-ähnlichen Syntax von JavaScript schreiben.
So installieren Sie die JavaScript-Bibliothek "select2", mit der mehrere Auswahlen von selectbox in Rails 6.0 in Mode kommen
[1st] RSpec-Anfänger haben versucht, Model Spec als Anfänger zu schreiben
Eine Sammlung von Mustern, die Sie kennen möchten, um den Code nicht zu komplizieren
Verschwenderische Verarbeitung von Sammlungen - ich möchte Ihnen die Möglichkeit geben, guten Code zu schreiben. 5 [C # Refactoring Sample]
Ich habe eine GitHub-Aktion erstellt, die es einfach macht, das Ausführungsergebnis von RSpec zu verstehen