用于集中响应处理的API调用的RxJava+Retroeft->BaseWatableforAPI调用

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (61)

到目前为止,我有一个抽象的CallbackClass,它实现了RetoFit回调。在那里,我捕获回调的“onResponse”和“onError”方法,并在最终转发到自定义实现的方法之前处理各种错误类型。我还使用这个集中式类来进行请求/响应、应用程序日志记录和其他事情。

例如:对于来自我的服务器的特定错误代码,我在响应体中接收一个新的Auth令牌,刷新令牌,然后clone.enQueue调用。当然,对于我的服务器的响应还有其他几种全局行为。

目前的解决方案(没有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();
    }

我的问题是:在最终将(或重试)链接(或重试)返回方法之前,有什么方法可以让这种集中的响应处理行为发生吗?

提问于
用户回答回答于

你提供的两个链接是一个非常好的起点,我用它来构造解决方案以对偶然事件做出反应

  • 网络错误有时是由于暂时缺少网络连接或切换到低吞吐量网络标准(如EDGE)导致SocketTimeoutException
  • 服务器错误 - >有时由于服务器超载而发生

我已经重写CallAdapter.Factory来处理错误并对它们做出适当的反应。

  1. RetryWithDelayIf从你找到的解决方案导入
  2. 重写CallAdapter.Factory以处理错误: 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 只是一个自定义的例外。
  3. 使用它 Retrofit.Builder Retrofit retrofit = new Retrofit.Builder() .addCallAdapterFactory(new RxCallAdapterFactoryWithErrorHandling()) .build();

用户回答回答于

你有没有考虑使用rxjava适配器进行改造? 在你的Gradle文件中添加https://mvnrepository.com/artifact/com.squareup.retrofit2/adapter-rxjava/2.1.0

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

这里是改造的界面

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

这是我的实现

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) {

                }
            });

请注意我正在使用gson转换器工厂来解析我的响应,以便返回pojo(Plain Ole Java对象)。

扫码关注云+社区