Soy relativamente nuevo en RXJava en general (realmente solo comencé a usarlo con RXJava2), y la mayoría de la documentación que puedo encontrar tiende a ser RXJava1; Por lo general, ahora puedo traducir entre ambos, pero todo el material reactivo es tan grande que es una API abrumadora con buena documentación (cuando puede encontrarla). Estoy tratando de optimizar mi código, y quiero hacerlo con pequeños pasos. El primer problema que quiero resolver es este patrón común que hago mucho en mi proyecto actual:
Tiene una solicitud que, si tiene éxito, utilizará para realizar una segunda solicitud.
Si alguno falla, debe poder identificar cuál falló. (principalmente para mostrar alertas de IU personalizadas).
Así es como suelo hacerlo ahora mismo:
(se omitió .subscribeOn/observeOn por simplicidad)
Single<FirstResponse> first = retrofitService.getSomething(); first .subscribeWith( new DisposableSingleObserver<FirstResponse>() { @Override public void onSuccess(final FirstResponse firstResponse) { // If FirstResponse is OK… Single<SecondResponse> second = retrofitService .getSecondResponse(firstResponse.id) //value from 1st .subscribeWith( new DisposableSingleObserver<SecondResponse>() { @Override public void onSuccess(final SecondResponse secondResponse) { // we're done with both! } @Override public void onError(final Throwable error) { //2nd request Failed, } }); } @Override public void onError(final Throwable error) { //firstRequest Failed, } });¿Hay una mejor manera de lidiar con esto en RXJava2?
flatMap y variaciones e incluso un Single.zip o similar, pero no estoy seguro de cuál es el patrón más fácil y común para lidiar con esto.
En caso de que se esté preguntando, FirstRequest obtendrá un Token real que necesito en SecondRequest. No se puede hacer una segunda solicitud sin el token.
Sugeriría usar un mapa plano (y retrolambda si esa es una opción). Además, no es necesario que mantenga el valor de retorno (por ejemplo, Single<FirstResponse> first ) si no está haciendo nada con él.
retrofitService.getSomething() .flatMap(firstResponse -> retrofitService.getSecondResponse(firstResponse.id) .subscribeWith(new DisposableSingleObserver<SecondResponse>() { @Override public void onSuccess(final SecondResponse secondResponse) { // we're done with both! } @Override public void onError(final Throwable error) { // a request request Failed, } });Este artículo me ayudó a pensar en estilos sobre cómo estructuro RxJava en general. Si es posible, desea que su cadena sea una lista de acciones de alto nivel para que pueda leerse como una secuencia de acciones/transformaciones.
EDITAR Sin lambdas, solo puede usar un Func1 para su flatMap. Hace lo mismo solo que mucho más código repetitivo.
retrofitService.getSomething() .flatMap(new Func1<FirstResponse, Observable<SecondResponse> { public void Observable<SecondResponse> call(FirstResponse firstResponse) { return retrofitService.getSecondResponse(firstResponse.id) } }) .subscribeWith(new DisposableSingleObserver<SecondResponse>() { @Override public void onSuccess(final SecondResponse secondResponse) { // we're done with both! } @Override public void onError(final Throwable error) { // a request request Failed, } });¿Esto no funciona para ti?
retrofitService .getSomething() .flatMap(firstResponse -> retrofitService.getSecondResponse(firstResponse.id)) .doOnNext(secondResponse -> {/* both requests succeeded */}) /* do more stuff with the response, or just subscribe */