我是RxJava的新手,所以如果这听起来太新手,请原谅我:-(。
到目前为止,我有一个抽象的回调类来实现 Retofit 回调。在那里,我捕获回调的"onResponse"和"onError"方法并处理各种错误类型,然后最终转发到自定义实现的方法。我还使用这个集中式类来记录请求/响应应用程序日志记录和其他内容。
例如:对于来自服务器的特定错误代码,我在响应正文中收到一个新的身份验证令牌,刷新令牌,然后克隆.排队调用。当然,我的服务器的响应还有其他几种全局行为。
当前解决方案(无 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();
}
我的问题是:在最终链接(或重试(回订阅者方法之前,有没有办法拥有这种集中式响应处理行为?
我发现这两个链接都有一个很好的起点,但不是具体的解决方案。任何帮助将不胜感激。
在 RxJava 中的自定义 API 异常后强制重试请求
改造 2 和 RxJava 错误处理运算符
您提供的两个链接是一个很好的起点,我用它来构建解决方案以应对意外情况
- 有时由于暂时缺乏网络连接或切换到低通量网络标准(如 EDGE(而导致网络错误,从而导致 SocketTimeoutException
- 服务器错误 - 有时由于服务器过载而>发生
我已经覆盖了CallAdapter.Factory
来处理错误并对其进行适当的反应。
-
从找到的解决方案导入
RetryWithDelayIf
-
覆盖
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
只是一个自定义例外。 -
在
Retrofit.Builder
中使用它Retrofit retrofit = new Retrofit.Builder() .addCallAdapterFactory(new RxCallAdapterFactoryWithErrorHandling()) .build();
另外:如果您希望解析来自 API 的错误(不调用 UnknownHostException
、HttpException
或 MalformedJsonException
等的错误(,您需要覆盖Factory
并在构建实例时使用自定义Retrofit
。解析响应并检查它是否包含错误。如果是,则抛出错误,错误将在上述方法中处理。
您是否考虑过使用 RXJAVA 适配器进行改造?https://mvnrepository.com/artifact/com.squareup.retrofit2/adapter-rxjava/2.1.0在您的 gradle 文件中添加
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(普通 Ole Java 对象(。
看看你怎么能做到。 下面是 api 调用和传递请求模型和响应模型。
public interface RestService {
//SEARCH_USER
@POST(SEARCH_USER_API_LINK)
Observable<SearchUserResponse> getSearchUser(@Body SearchUserRequest getSearchUserRequest);
}
这是改造电话,我用了改造2
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();
}
这是 api 调用,在您的活动中调用它。
@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()) {
}
});
}
希望这对您有所帮助。