我使用retrofit2与Rx。我有两个API调用。如果第一次调用返回代码400的空响应,我需要进行第二次API调用,如果不是,那么只是显示结果。我实现了如下所示的自定义错误处理。下面是我的解决方案:
getResponse1(token)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new ObserverErrorImpl<Response1, BaseError>(BaseError.class) {
@Override
public void onNext(Response1 response) {
view.onSuccess(response);
}
@Override
public void onClientError(BaseError response) {
getResponse2(token)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new ObserverErrorImpl<Response2, BaseError>(BaseError.class) {
@Override
public void onNext(Response2 response) {
view.onSuccess(response);
view.hideProgress();
}
@Override
public void onError(Throwable throwable) {
super.onError(throwable);
view.hideProgress();
}
});
}
@Override
public void onError(Throwable throwable) {
super.onError(throwable);
view.hideProgress();
}
});
是否有可能简化方法onClientError
内部的代码?这是一个好的解决方案吗?
1)。为了简化它,Response1
和Response2
最好扩展一些基类,这样在您的链中,您可以使用基类操作,可以在需要时将其转换为特定类型
那么,让我们假设,你有BaseResponse
:
public abstract class BaseResponse{
public static int TYPE_RESPONSE_1 = 1;
public static int TYPE_RESPONSE_2 = 2;
public abstract int getType(); //every class MUST override this method
}
Response1
和Response2
应该覆盖BaseResponse
2)。 getResponse1
和getResponse2
应该返回Observable<BaseResponse>
3)。目标代码:
getResponse1(token)
.onErrorResumeNext(new Func1<Throwable, Observable<BaseResponse>>() {
@Override
public Observable<BaseResponse> call(Throwable throwable) {
// I use Retrofit 1.9
// And in Retrofit 1.9 I have class RetrofitError, which may provide me all info about error
// I'm absolutelly sure Retrofit 2 also have such class,
// but it may have another name
if(/* is your target error */){
//cast it tour target error
return getResponse2(token);
}
return Observable.error(throwable);
}
})
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new ObserverErrorImpl<Response1, BaseError>(BaseError.class) {
@Override
public void onNext(BaseResponse response) {
if(response.getType() == BaseResponse.TYPE_RESPONSE_1){
view.onSuccess(response);
} else {
view.onSuccess(response);
view.hideProgress();
}
}
@Override
public void onError(Throwable throwable) {
super.onError(throwable);
view.hideProgress();
}
});
天哪,为什么每个人都把事情弄得这么复杂?在实践中,我觉得每次我需要订阅另一个subscribe
中的Observable
时,都有一个操作符可以为我做得更干净:
<T,E extends Throwable> Observable<T>
whenExceptionIs(Class<E> what, Func1<E,Observable<T>> result) {
return t -> {
return what.isInstance(t) ? result.call(t) : Observable.error(t);
};
}
getResponse1(token)
.onErrorResumeNext(whenExceptionIs(BaseError.class, getResponse2(token)))
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(view::onSuccess, view::hideProgress, err -> view.hideProgress());
如果您有特殊的错误处理需求,创建一个自定义的Subscriber
来处理它,但要确保错误处理通常是
- 在
Observable
链中处理,如果它可以对此做任何事情(忽略它,重试调用等) - 下游传播。