Konvertieren synchroner und asynchroner APIs in Observables mithilfe von RxJava2

Konvertieren von synchronen und asynchronen APIs in Observables mithilfe von RxJava2

1. Überblick

In diesem Tutorial lernen wir die Operatoren vonhow to transform traditional synchronous and asynchronous APIs into Observables using RxJava2kennen.

Wir werden einige einfache Funktionen erstellen, mit denen wir diese Operatoren ausführlich besprechen können.

2. Maven-Abhängigkeiten

Zuerst müssen wirRxJava2 undRxJava2Extensions als Maven-Abhängigkeiten hinzufügen:


    io.reactivex.rxjava2
    rxjava
    2.2.2


    com.github.akarnokd
    rxjava2-extensions
    0.20.4

3. Die Betreiber

RxJava2 definierta whole lot of operators für verschiedene Anwendungsfälle der reaktiven Programmierung.

Wir werden jedoch nur einige Operatoren diskutieren, die üblicherweise zum Konvertieren synchroner oder asynchroner Methoden inObservables verwendet werden, basierend auf ihrer Art. These operators take functions as arguments and emit the value returned from that function.

Neben den normalen Operatoren definiert RxJava2 einige weitere Operatoren für erweiterte Funktionen.

Lassen Sie uns erforschen, wie wir diese Operatoren nutzen können, um synchrone und asynchrone Methoden zu konvertieren.

4. Synchrone Methodenkonvertierung

4.1. Verwenden vonfromCallable()

Dieser Operator gibt einObservable zurück, das, wenn ein Abonnent es abonniert, die als Argument übergebene Funktion aufruft und dann den von dieser Funktion zurückgegebenen Wert ausgibt. Erstellen wir eine Funktion, die eine Ganzzahl zurückgibt, und transformieren sie:

AtomicInteger counter = new AtomicInteger();
Callable callable = () -> counter.incrementAndGet();

Jetzt transformieren wir es inObservable und testen es, indem wir es abonnieren:

Observable source = Observable.fromCallable(callable);

for (int i = 1; i < 5; i++) {
    source.test()
      .awaitDone(5, TimeUnit.SECONDS)
      .assertResult(i);
    assertEquals(i, counter.get());
}

The fromCallable() operator executes the specified function lazily each time when the wrapped Observable gets subscribed. Um dieses Verhalten zu testen, haben wir mehrere Abonnenten mithilfe einer Schleife erstellt.

Da reaktive Streams standardmäßig asynchron sind, kehrt der Abonnent sofort zurück. In den meisten praktischen Szenarien hat die aufrufbare Funktion eine gewisse Verzögerung, um ihre Ausführung abzuschließen. Alsowe’ve added a maximum wait time of five seconds vor dem Testen des Ergebnisses unserer aufrufbaren Funktion.

Beachten Sie auch, dass wir dieObservabletest()-Methode vonObservableverwendet haben. This method is handy when testing Observables. Es wird einTestObserver and erstellt, der unsereObservable. abonniert

4.2. Verwenden vonstart()

Der Operatorstart() ist Teil des ModulsRxJava2Extension. Es ruft die angegebene Funktion asynchron auf und gibt einObservable zurück, das das Ergebnis ausgibt:

Observable source = AsyncObservable.start(callable);

for (int i = 1; i < 5; i++) {
    source.test()
      .awaitDone(5, TimeUnit.SECONDS)
      .assertResult(1);
    assertEquals(1, counter.get());
}

Die Funktion wird sofort aufgerufen, nicht immer dann, wenn ein Teilnehmer die resultierendenObservable abonniert. Multiple subscriptions to this observable observe the same return value.

5. Asynchrone Methodenkonvertierung

5.1. Verwenden vonfromFuture()

Wie wir wissen, ist die häufigste Methode zum Erstellen einer asynchronen Methode in Java die Implementierung vonFuture. Die MethodefromFuture verwendet ein ArgumentFuture und gibt den Wert aus, der mit der MethodeFuture.get() erhalten wurde.

Lassen Sie uns zunächst die zuvor erstellte Funktion asynchron machen:

ExecutorService executor = Executors.newSingleThreadExecutor();
Future future = executor.submit(callable);

Als nächstes führen wir die Tests durch, indem wir sie transformieren:

Observable source = Observable.fromFuture(future);

for (int i = 1; i < 5; i++) {
    source.test()
      .awaitDone(5, TimeUnit.SECONDS)
      .assertResult(1);
    assertEquals(1, counter.get());
}
executor.shutdown();

Beachten Sie erneut, dass jedes Abonnement denselben Rückgabewert aufweist.

Jetzt ist diedispose()-Methode vonObservable wirklich hilfreich, wenn es um die Verhinderung von Speicherlecks geht. In diesem Fall wird die Zukunft jedoch nicht abgebrochen, daFuture.get() blockiert.

Wir können also sicherstellen, dass die Zukunft durch die Funktioncombining the doOnDispose() der beobachtbarensource und die Methodecancel auffuture aufgehoben wird:

source.doOnDispose(() -> future.cancel(true));

5.2. Verwenden vonstartFuture()

Wie der Name schon sagt, startet dieser Operator sofort die angegebenenFuture und gibt den Rückgabewert aus, wenn ein Abonnent ihn abonniert. Im Gegensatz zum OperatorfromFuture, der das Ergebnis für die nächste Verwendung zwischenspeichert, istthis operator will execute the asynchronous method each time when it gets subscribed:

ExecutorService executor = Executors.newSingleThreadExecutor();
Observable source = AsyncObservable.startFuture(() -> executor.submit(callable));

for (int i = 1; i < 5; i++) {
    source.test()
      .awaitDone(5, TimeUnit.SECONDS)
      .assertResult(i);
    assertEquals(i, counter.get());
}
executor.shutdown();

5.3. Verwenden vondeferFuture()

This operator aggregates multiple Observables returned from a Future method and returns a stream of return values obtained from each Observable. Hiermit wird die übergebene asynchrone Factory-Funktion gestartet, wenn sich ein neuer Teilnehmer anmeldet.

Erstellen wir also zuerst die asynchrone Factory-Funktion:

List list = Arrays.asList(new Integer[] { counter.incrementAndGet(),
  counter.incrementAndGet(), counter.incrementAndGet() });
ExecutorService exec = Executors.newSingleThreadExecutor();
Callable> callable = () -> Observable.fromIterable(list);

Und dann können wir einen kurzen Test machen:

Observable source = AsyncObservable.deferFuture(() -> exec.submit(callable));
for (int i = 1; i < 4; i++) {
    source.test()
      .awaitDone(5, TimeUnit.SECONDS)
      .assertResult(1,2,3);
}
exec.shutdown();

6. Fazit

In diesem Tutorial haben wir gelernt, wie Sie synchrone und asynchrone Methoden in RxJava2-Observables umwandeln.

Die hier gezeigten Beispiele sind natürlich die grundlegenden Implementierungen. Wir können RxJava2 jedoch für komplexere Anwendungen wie Video-Streaming und Anwendungen verwenden, bei denen große Datenmengen in Portionen gesendet werden müssen.

Wie üblich finden Sie alle kurzen Beispiele, die wir hier besprochen haben, aufGithub project.