我正在尝试在全局级别处理应用程序中的异常,因此改造会抛出一个错误,我会在某个特定的类中捕获它,并使用逻辑来处理这些错误。
我有一个界面
@POST("/token")
AuthToken refreshToken(@Field("grant_type") String grantType, @Field("refresh_token") String refreshToken);
和observables
/**
* Refreshes auth token
*
* @param refreshToken
* @return
*/
public Observable<AuthToken> refreshToken(String refreshToken) {
return Observable.create((Subscriber<? super AuthToken> subscriber) -> {
try {
subscriber.onNext(apiManager.refreshToken(REFRESH_TOKEN, refreshToken));
subscriber.onCompleted();
} catch (Exception e) {
subscriber.onError(e);
}
}).subscribeOn(Schedulers.io());
}
当我从服务器获得401(无效令牌或其他一些网络相关错误)时,我想刷新令牌并重复其余的呼叫。是否有一种方法可以使用rxjava对所有其余的调用执行此操作,并使用某种可观察的方法来全局捕获此错误,处理它并重复抛出它的调用?
现在我正在使用subject来捕获.subscribe()这样的错误
private static BehaviorSubject errorEvent = BehaviorSubject.create();
public static BehaviorSubject<RetrofitError> getErrorEvent() {
return errorEvent;
}
并在一些电话中
getCurrentUser = userApi.getCurrentUser().observeOn(AndroidSchedulers.mainThread())
.subscribe(
(user) -> {
this.user = user;
},
errorEvent::onNext
);
然后在我的主要活动中,我订阅了该行为主题并解析了错误
SomeApi.getErrorEvent().subscribe(
(e) -> {
//parse the error
}
);
但我无法重复调用抛出错误的observable。
答案 0 :(得分:39)
您需要使用运算符onErrorResumeNext(Func1 resumeFunction)
,在official wiki:
onErrorResumeNext()方法返回一个Observable,它反映了源Observable的行为,除非Observable在这种情况下调用onError(),而不是将该错误传播给Subscriber,onErrorResumeNext()而是开始镜像第二个备份Observable
在你的情况下,我会这样做:
getCurrentUser = userApi.getCurrentUser()
.onErrorResumeNext(refreshTokenAndRetry(userApi.getCurrentUser()))
.observeOn(AndroidSchedulers.mainThread())
.subscribe(...)
其中:
private <T> Func1<Throwable,? extends Observable<? extends T>> refreshTokenAndRetry(final Observable<T> toBeResumed) {
return new Func1<Throwable, Observable<? extends T>>() {
@Override
public Observable<? extends T> call(Throwable throwable) {
// Here check if the error thrown really is a 401
if (isHttp401Error(throwable)) {
return refreshToken().flatMap(new Func1<AuthToken, Observable<? extends T>>() {
@Override
public Observable<? extends T> call(AuthToken token) {
return toBeResumed;
}
});
}
// re-throw this error because it's not recoverable from here
return Observable.error(throwable);
}
};
}
另请注意,此函数可以在其他情况下轻松使用,因为它不会使用已恢复的Observable发出的实际值进行输入。
答案 1 :(得分:1)
<div-tmp