Wann sollte man die MethodescribeWith anstelle des einfachen Abonnements aufrufen? Und was ist der Anwendungsfall?
compositeDisposable.add(get()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(this::handleResponse, this::handleError));
VS
compositeDisposable.add(get()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
// .subscribe(this::handleResponse, this::handleError);
.subscribeWith(new DisposableObserver<News>() {
@Override public void onNext(News value) {
handleResponse(value);
}
@Override public void onError(Throwable e) {
handleError(e);
}
@Override public void onComplete() {
// dispose here ? why? when the whole thing will get disposed later
//via compositeDisposable.dispose(); in onDestroy();
}
}));
Vielen Dank
Später hinzugefügt
Laut Dokumentation geben beide Einweg-SingleObserver-Instanzen zurück:
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public final <E extends SingleObserver<? super T>> E subscribeWith(E observer) {
subscribe(observer);
return observer;
}
@SchedulerSupport(SchedulerSupport.NONE)
public final Disposable subscribe(final Consumer<? super T> onSuccess, final Consumer<? super Throwable> onError) {
ObjectHelper.requireNonNull(onSuccess, "onSuccess is null");
ObjectHelper.requireNonNull(onError, "onError is null");
ConsumerSingleObserver<T> s = new ConsumerSingleObserver<T>(onSuccess, onError);
subscribe(s);
return s;
}
Dabei implementiert die ConsumerSingleObserver-Klasse SingleObserver und Disposable.
Observable#subscribe-Erklärung:
In Ihrem ersten Code-Snippet:
.subscribe(this::handleResponse, this::handleError));
Sie verwenden tatsächlich eine der mehreren überladenen Observable#subscribe
Methoden:
public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError)
Es gibt noch einen, der auch einen aufnimmt Action
ausführen beiComplete:
public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError,
Action onComplete) {
Und eine weitere Option ermöglicht es Ihnen, einfach eine zu übergeben Observer
(HINWEIS: Void-Methode) (Bearbeiten 2 – diese Methode ist definiert in ObservableSource
das ist die Schnittstelle, die Observable
erweitert.)
public final void subscribe(Observer<? super T> observer)
Im zweiten Code-Snippet in Ihrer Frage haben Sie die subscribeWith
Methode, die einfach die zurückgibt Observer
Sie übergeben (aus Gründen der Bequemlichkeit / Zwischenspeicherung usw.):
public final <E extends Observer<? super T>> E subscribeWith(E observer)
Beobachter#onVollständige Erklärung:
Observer#onComplete wird aufgerufen, nachdem Observable alle Elemente im Stream ausgegeben hat. Aus dem Java-Dokument:
/**
* Notifies the Observer that the {@link Observable} has finished sending push-based notifications.
* <p>
* The {@link Observable} will not call this method if it calls {@link #onError}.
*/
void onComplete();
Also zum Beispiel, wenn die get()
in Ihren Code-Snippets zurückgegeben an Observable
das mehrfach emittiert News
Objekte, jeder wird in behandelt Observer#onNext
. Hier können Sie jeden Artikel bearbeiten.
Nachdem sie alle verarbeitet wurden (und vorausgesetzt, dass kein Fehler aufgetreten ist), wird die onComplete
wird angerufen. Hier können Sie alle zusätzlichen Aktionen ausführen, die Sie ausführen müssen (z. B. die Benutzeroberfläche aktualisieren), in dem Wissen, dass Sie alle verarbeitet haben News
Objekte.
Damit ist nicht zu verwechseln Disposable#dispose
die aufgerufen wird, wenn der beobachtbare Stream endet (complete/error), oder manuell von Ihnen, um die Beobachtung zu beenden (hier befindet sich die CompositeDisposable
kommt herein, da es Ihnen hilft, alle Ihre zu entsorgen Disposable
s, die es sofort enthält).
Wenn in Ihrem Szenario die get()
wird ein zurückgeben Observable
die nur ein einzelnes Element ausgibt, dann statt einer Observable
erwägen Sie die Verwendung von an io.reactivex.Single
wo Sie nur das eine Element bearbeiten (in onSuccess
) und muss keine angeben Action
für onComplete 🙂
Bearbeiten: Antwort auf deinen Kommentar:
Allerdings kann ich SubscribeWith immer noch nicht verwenden. Sie sagten, es übergibt den Beobachter zum Caching usw., wohin geht es? auf komplett? und von dem, was ich verstanden habe, verbraucht “subscribeWith” nicht wirklich das Observable (oder Single), oder?
Zur weiteren Klärung der subscribeWith
Erklärung, was ich meinte war, dass es Wille verbrauchen die Observer
Objekt, das Sie an übergeben haben subscribeWith
(genau wie die subscribe
-Methode), aber es wird auch denselben Beobachter direkt an Sie zurücksenden. Zum Zeitpunkt des Verfassens dieses Artikels lautet die Implementierung vonscribeWith:
public final <E extends Observer<? super T>> E subscribeWith(E observer) {
subscribe(observer);
return observer;
}
Deswegen, subscribeWith
kann austauschbar mit verwendet werden subscribe
.
Können Sie einen Anwendungsfall von “subscribeWith” mit einem Beispiel geben? Ich denke, das wird die Frage vollständig beantworten
Das subscribeWith
javadoc gibt das folgende Verwendungsbeispiel:
Observable<Integer> source = Observable.range(1, 10);
CompositeDisposable composite = new CompositeDisposable();
ResourceObserver<Integer> rs = new ResourceObserver<>() {
// ...
};
composite.add(source.subscribeWith(rs));
Siehe hier die Verwendung von subscribeWith
werde das gleiche zurückgeben ResourceObserver
Objekt, das instanziiert wurde. Dies bietet den Komfort, das Abonnement durchzuführen und die hinzuzufügen ResourceObserver
zum CompositeDisposable
in einer Zeile (beachten Sie, dass ResourceObservable
implementiert Disposable
.)
Bearbeiten 2 Antwort auf den zweiten Kommentar.
source.subscribeWith(rs); source.subscribe(rs); beide geben die SingleObserver-Instanz zurück,
ObservableSource#subscribe(Observer <? super T> observer)
nicht Rückkehr ein Observer
. Es ist eine ungültige Methode (siehe HINWEIS unter der Beobachtbar#abonnieren Erklärung oben.) Während die Observable#subscribeWith
TUT Gib die … wieder Observer
. Wenn wir den Beispielverwendungscode mit neu schreiben würden ObservableSource#subscribe
Stattdessen müssten wir es in zwei Zeilen wie folgt tun:
source.subscribe(rs); //ObservableSource#subscribe is a void method so nothing will be returned
composite.add(rs);
Während die Observable#subscribeWith
Methode machte es uns bequem, das Obige in nur einer Zeile zu erledigen composite.add(source.subscribeWith(rs));
Es kann verwirrend werden mit all den überladenen Subscribe-Methoden, die etwas ähnlich aussehen, aber es gibt Unterschiede (von denen einige subtil sind). Ein Blick auf den Code und die Dokumentation hilft bei der Unterscheidung zwischen ihnen.
Bearbeiten 3 Ein weiteres Anwendungsbeispiel für „subscribeWith“.
Das subscribeWith
-Methode ist nützlich, wenn Sie eine bestimmte Implementierung einer haben Observer
die Sie vielleicht wiederverwenden möchten. Im obigen Beispielcode wurde beispielsweise eine spezifische Implementierung von bereitgestellt ResourceObserver
im Abonnement, wodurch dessen Funktionalität geerbt wird, während Sie weiterhin onNext onError und onComplete behandeln können.
Ein weiteres Verwendungsbeispiel: für den Beispielcode in Ihrer Frage, was wäre, wenn Sie dasselbe Abonnement für die ausführen möchten get()
Antwort an mehreren Stellen?
Anstatt die zu kopieren Consumer
Implementierungen für onNext und onError über verschiedene Klassen hinweg, was Sie stattdessen tun können, ist eine neue Klasse für zB zu definieren.
//sample code..
public class GetNewsObserver extends DisposableObserver<News> {
//implement your onNext, onError, onComplete.
....
}
Nun, wann immer Sie das tun get()
Anfrage, können Sie einfach abonnieren, indem Sie Folgendes tun:
compositeDisposable.add(get()
...
.subscribeWith(new GetNewsObserver()));
Sehen Sie, der Code ist jetzt einfach, Sie behalten die Trennung der Verantwortung für die Bearbeitung der Antwort bei und können diese jetzt wiederverwenden GetNewsObserver
wo immer Sie wollen.
Dank @Simbatrons Antwort, um den spezifischen Anwendungsfall (nach dem, was ich verstanden habe) zusammenzufassen, ist, wenn Sie denselben Beobachter haben, den Sie an verschiedene Observable binden möchten, verwenden Sie “subscribeWith”. (damit mehrere Observables dieselbe Observer-Implementierung verwenden können). Bitte fügen Sie Ihren Kommentar hinzu, wenn Sie der Meinung sind, dass dies nicht der einzige Unterschied im Anwendungsfall ist
– bastami82
15. Juli 2017 um 8:03 Uhr
Ich frage mich dasselbe – meiner Meinung nach ist Ihr erstes Snippet viel sauberer mit der Verwendung von Lambdas usw. Also ja, es scheint, als ob der seltene Fall, dass Sie denselben Observer wiederverwenden möchten, das einzige Mal ist, dass Sie .subscribeWith() benötigen? Es ist seltsam, dass die Dokumente die überladene Variante von Subscribe nicht wirklich erwähnen, die das Disposable zurückgibt. Stattdessen weisen sie Sie nur darauf hin, das neue und unhandliche SubscribeWith() zu verwenden.
– Verbrennungsanlage
11. Oktober 2017 um 12:35 Uhr