squareup rxjava2 rxjava example ejemplo and android rx-java retrofit2 rx-android

android - rxjava2 - RxJava+Retrofit-> BaseObservable para llamadas a la API para el manejo centralizado de respuestas



retrofit2 and rxjava2 (3)

Soy nuevo en RxJava, por favor, perdóneme si esto suena demasiado novato :-).

A partir de ahora tengo un resumen de CallbackClass que implementa el Retofit Callback. Allí detecto los métodos "onResponse" y "onError" de Callback y manejo varios tipos de error antes de reenviarlos a los métodos implementados personalizados. También utilizo esta clase centralizada para el registro de aplicaciones de solicitud / respuesta y otras cosas.

Por ejemplo: para códigos de error específicos de mi servidor, recibo un nuevo token de Autenticación en el cuerpo de la respuesta, actualizo el token y luego clone. Por supuesto, hay varios otros comportamientos globales a las respuestas de mi servidor.

Solución actual (sin Rx):

public abstract void onResponse(Call<T> call, Response<T> response, boolean isSuccess); public abstract void onFailure(Call<T> call, Response<T> response, Throwable t, boolean isTimeout); @Override public void onResponse(Call<T> call, Response<T> response) { if (_isCanceled) return; if (response != null && !response.isSuccessful()) { if (response.code() == "SomeCode" && retryCount < RETRY_LIMIT) { TokenResponseModel newToken = null; try { newToken = new Gson().fromJson(new String(response.errorBody().bytes(), "UTF-8"), TokenResponseModel.class); } catch (Exception e) { e.printStackTrace(); } SomeClass.token = newToken.token; retryCount++; call.clone().enqueue(this); return; } } } else { onResponse(call, response, true); removeFinishedRequest(); return; } onFailure(call, response, null, false); removeFinishedRequest(); } @Override public void onFailure(Call<T> call, Throwable t) { if (_isCanceled) return; if (t instanceof UnknownHostException) if (eventBus != null) eventBus.post(new NoConnectionErrorEvent()); onFailure(call, null, t, false); removeFinishedRequest(); }

Mi pregunta es: ¿Hay alguna forma de tener este tipo de comportamiento de manejo de respuesta centralizado antes de finalmente encadenar (o volver a intentarlo) a los métodos del suscriptor?

Encontré estos 2 enlaces que tienen un buen punto de partida pero no una solución concreta. Cualquier ayuda sería realmente apreciada.

Forzar el reintento de la solicitud después de las excepciones de API personalizadas en RxJava

Retrofit 2 y RxJava manejo de errores operadores


¿Ha considerado usar el adaptador rxjava para la adaptación? https://mvnrepository.com/artifact/com.squareup.retrofit2/adapter-rxjava/2.1.0 en su archivo gradle agregue

compile ''com.squareup.retrofit2:adapter-rxjava:2.1.0''

Aquí hay una interfaz para la actualización

public interface Service { @GET("userauth/login?") Observable<LoginResponse> getLogin( @Query("v") String version, @Query("username") String username, @Query("password") String password); }

y aquí está mi implementación

Service.getLogin( VERSION, "username", "password") .subscribe(new Subscriber<LoginResponse>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(LoginResponse loginResponse) { } });

tenga en cuenta que estoy usando la fábrica de convertidores de gson para analizar mi respuesta, así que me devuelven un pojo (objeto Java de Plain Ole).


Dos enlaces que proporcionaste son un muy buen punto de partida, que utilicé para construir una solución que reaccione a los accidentes

  • los errores de red ocurren a veces debido a la falta temporal de conexión a la red, o el cambio a un estándar de red de bajo rendimiento, como EDGE, que causa la excepción SocketTimeoutException
  • errores del servidor -> ocurren a veces debido a la sobrecarga del servidor

He CallAdapter.Factory para manejar los errores y reaccionar adecuadamente ante ellos.

  1. Importe RetryWithDelayIf desde la solution que encontró

  2. Reemplace CallAdapter.Factory para manejar errores:

    public class RxCallAdapterFactoryWithErrorHandling extends CallAdapter.Factory { private final RxJavaCallAdapterFactory original; public RxCallAdapterFactoryWithErrorHandling() { original = RxJavaCallAdapterFactory.create(); } @Override public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) { return new RxCallAdapterWrapper(retrofit, original.get(returnType, annotations, retrofit)); } public class RxCallAdapterWrapper implements CallAdapter<Observable<?>> { private final Retrofit retrofit; private final CallAdapter<?> wrapped; public RxCallAdapterWrapper(Retrofit retrofit, CallAdapter<?> wrapped) { this.retrofit = retrofit; this.wrapped = wrapped; } @Override public Type responseType() { return wrapped.responseType(); } @SuppressWarnings("unchecked") @Override public <R> Observable<?> adapt(final Call<R> call) { return ((Observable) wrapped.adapt(call)).onErrorResumeNext(new Func1<Throwable, Observable>() { @Override public Observable call(Throwable throwable) { Throwable returnThrowable = throwable; if (throwable instanceof HttpException) { HttpException httpException = (HttpException) throwable; returnThrowable = httpException; int responseCode = httpException.response().code(); if (NetworkUtils.isClientError(responseCode)) { returnThrowable = new HttpClientException(throwable); } if (NetworkUtils.isServerError(responseCode)) { returnThrowable = new HttpServerException(throwable); } } if (throwable instanceof UnknownHostException) { returnThrowable = throwable; } return Observable.error(returnThrowable); } }).retryWhen(new RetryWithDelayIf(3, DateUtils.SECOND_IN_MILLIS, new Func1<Throwable, Boolean>() { @Override public Boolean call(Throwable throwable) { return throwable instanceof HttpServerException || throwable instanceof SocketTimeoutException || throwable instanceof UnknownHostException; } })); } } }

    HttpServerException es solo una excepción personalizada.

  3. Úsalo en Retrofit.Builder

    Retrofit retrofit = new Retrofit.Builder() .addCallAdapterFactory(new RxCallAdapterFactoryWithErrorHandling()) .build();

Extra : si desea analizar los errores que provienen de la API (error que no invoca UnknownHostException , HttpException o MalformedJsonException o etc.), debe anular Factory y usar uno personalizado durante la creación de la instancia de Retrofit . Analizar la respuesta y comprobar si contiene errores. Si es así, el error de error se manejará dentro del método anterior.


Mira cómo puedes hacerlo. Aquí está el api call y pass Modelo de solicitud y modelo de respuesta en esto.

public interface RestService { //SEARCH_USER @POST(SEARCH_USER_API_LINK) Observable<SearchUserResponse> getSearchUser(@Body SearchUserRequest getSearchUserRequest); }

Esta es la llamada de reequipamiento, usé retrofit2

public RestService getRestService() { Retrofit retrofit = new Retrofit.Builder() .baseUrl(ApiConstants.BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .client(getOkHttpClient()) .build(); return retrofit.create(RestService.class); } //get OkHttp instance @Singleton @Provides public OkHttpClient getOkHttpClient() { HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(); httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient.Builder builder = new OkHttpClient.Builder(); builder.interceptors().add(httpLoggingInterceptor); builder.readTimeout(60, TimeUnit.SECONDS); builder.connectTimeout(60, TimeUnit.SECONDS); return builder.build(); }

Esta es la llamada api, llámala en tu actividad.

@Inject Scheduler mMainThread; @Inject Scheduler mNewThread; //getSearchUser api method public void getSearchUser(String user_id, String username) { SearchUserRequest searchUserRequest = new SearchUserRequest(user_id, username); mObjectRestService.getSearchUser(searchUserRequest). subscribeOn(mNewThread). observeOn(mMainThread). subscribe(searchUserResponse -> { Timber.e("searchUserResponse :" + searchUserResponse.getResponse().getResult()); if (isViewAttached()) { getMvpView().hideProgress(); if (searchUserResponse.getResponse().getResult() == ApiConstants.STATUS_SUCCESS) { } else { } } }, throwable -> { if (isViewAttached()) { } }); }

Espero que esto te ayudará.