android - rxjava - rxkotlin
¿Suscribirse con Vs suscribirse en RxJava2(Android)? (1)
Observable # explicación de suscripción:
En tu primer fragmento de código:
.subscribe (this :: handleResponse, this :: handleError));
En realidad, está utilizando uno de los varios métodos de Observable#subscribe
sobrecargados:
public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError)
Hay otro que también toma una Action
para realizar en Completo:
public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError,
Action onComplete) {
Y otra opción le permite simplemente pasar un Observer
(NOTA: método de anulación) (Edición 2: este método se define en ObservableSource
, que es la interfaz que se extiende en Observable
).
public final void subscribe(Observer<? super T> observer)
En el segundo fragmento de código de su pregunta, usó el método subscribeWith
que simplemente devuelve el Observer
que pasó (por conveniencia / almacenamiento en caché, etc.):
public final <E extends Observer<? super T>> E subscribeWith(E observer)
Observador # en Explicación completa:
Observador # onComplete recibe una llamada después de que el Observable ha emitido todos los elementos en la transmisión. Desde el documento java:
/**
* 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();
Entonces, por ejemplo, si el get()
en sus fragmentos de código devolvió un Observable
que emitió múltiples objetos de News
, cada uno se manejará en el Observer#onNext
. Aquí puedes procesar cada elemento.
Después de que todos hayan sido procesados (y suponiendo que no haya ocurrido ningún error), se onComplete
a onComplete
. Aquí puede realizar cualquier acción adicional que necesite realizar (por ejemplo, actualizar UI) sabiendo que ha procesado todos los objetos de News
.
Esto no debe confundirse con el Disposable#dispose
que se invoca cuando finaliza el flujo observable (completo / error), o manualmente para finalizar la observación (aquí es donde entra en CompositeDisposable
el CompositeDisposable
ya que le ayuda a deshacerse de todos sus Disposable
). que contiene a la vez).
Si en su escenario, el get()
devolverá un Observable
que solo emite un solo elemento, entonces en lugar de usar un Observable
, considere usar un io.reactivex.Single
donde solo procesa el único elemento (en onSuccess
), y no lo hará. Necesito especificar una Action
para onComplete :)
Editar : respuesta a tu comentario:
Sin embargo, todavía no utilizo subscribeWith, usted dijo que pasa el observador para el almacenamiento en caché, etc. ¿A dónde pasa? en completo? y por lo que entendí, suscribirme con no está consumiendo el derecho observable (o único).
Para aclarar aún más la subscribeWith
explicación, lo que quise decir es que consumirá el objeto Observer
que pasaste a la subscribeWith
(exactamente igual que el método de subscribe
), sin embargo, también te devolverá ese mismo Observer. Al momento de escribir, la implementación de subscribeWith es:
public final <E extends Observer<? super T>> E subscribeWith(E observer) {
subscribe(observer);
return observer;
}
Por lo tanto, subscribeWith
se puede usar indistintamente con subscribe
.
¿Puedes dar un caso de uso de subscribeWith con ejemplo? Supongo que eso responderá la pregunta completamente.
SubscribeWith javadoc da el siguiente ejemplo de uso:
Observable<Integer> source = Observable.range(1, 10);
CompositeDisposable composite = new CompositeDisposable();
ResourceObserver<Integer> rs = new ResourceObserver<>() {
// ...
};
composite.add(source.subscribeWith(rs));
Vea aquí el uso de subscribeWith
devolverá el mismo objeto ResourceObserver
que se creó una instancia. Esto brinda la conveniencia de realizar la suscripción y agregar el ResourceObserver
al CompositeDisposable
en una línea (tenga en cuenta que ResourceObservable
implementa Disposable
).
Editar 2 Respondiendo al segundo comentario.
source.subscribeWith (rs); fuente.subscribe (rs); ambos devuelven instancia de SingleObserver,
ObservableSource#subscribe(Observer <? super T> observer)
NO devuelve un Observer
. Es un método nulo (vea la NOTA en la explicación de suscripción de Observable # arriba). Mientras que la Observer
Observable#subscribeWith
devuelve el Observer
. Si tuviéramos que volver a escribir el código de uso de ejemplo utilizando ObservableSource#subscribe
lugar, tendríamos que hacerlo en dos líneas así:
source.subscribe(rs); //ObservableSource#subscribe is a void method so nothing will be returned
composite.add(rs);
Mientras que el método Observable#subscribeWith
hizo que sea conveniente para nosotros hacer lo anterior en una sola línea composite.add(source.subscribeWith(rs));
Puede confundirse con todos los métodos de suscripción sobrecargados que parecen algo similares, sin embargo, existen diferencias (algunas de las cuales son sutiles). Mirar el código y la documentación ayuda a proporcionar la distinción entre ellos.
Edición 3 Otro caso de uso de muestra para subscribeWith El método subscribeWith
es útil cuando tiene una implementación específica de un Observer
que tal vez desee reutilizar. Por ejemplo, en el código de ejemplo anterior, proporcionó una implementación específica de ResourceObserver
en la suscripción, heredando así su funcionalidad y al mismo tiempo le permite manejar onNext onError y onComplete.
Otro ejemplo de uso: para el código de muestra en su pregunta, ¿qué sucede si desea realizar la misma suscripción para la respuesta get()
en varios lugares?
En lugar de copiar las implementaciones de Consumer
para onNext y onError en diferentes clases, lo que puede hacer en su lugar es definir una nueva clase para, por ejemplo.
//sample code..
public class GetNewsObserver extends DisposableObserver<News> {
//implement your onNext, onError, onComplete.
....
}
Ahora, cuando haga esa solicitud get()
, simplemente puede suscribirse haciendo lo siguiente:
compositeDisposable.add(get()
...
.subscribeWith(new GetNewsObserver()));
Ver que el código es simple ahora, mantienes la separación de responsabilidad para manejar la respuesta y ahora puedes reutilizar ese GetNewsObserver
donde quieras.
¿Cuándo llamar al método subscribeWith en lugar de la suscripción simple? ¿Y cuál es el caso de uso?
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();
}
}));
Gracias
Añadido más tarde
Según la documentación, ambos devuelven instancias desechables de SingleObserver:
@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;
}
Donde la clase ConsumerSingleObserver implementa SingleObserver y Disposable.