Android 使用rxjava进行改造,以全局方式处理网络异常

Android 使用rxjava进行改造,以全局方式处理网络异常,android,retrofit,rx-java,Android,Retrofit,Rx Java,我试图在全局级别上处理应用程序中的异常,所以改型会抛出一个错误,我在某个特定类中捕获到它,并使用处理这些错误的逻辑 我有一个接口 @POST("/token") AuthToken refreshToken(@Field("grant_type") String grantType, @Field("refresh_token") String refreshToken); 和可观察到的 /** * Refreshes auth token * * @param refreshToken

我试图在全局级别上处理应用程序中的异常,所以改型会抛出一个错误,我在某个特定类中捕获到它,并使用处理这些错误的逻辑

我有一个接口

@POST("/token")
AuthToken refreshToken(@Field("grant_type") String grantType, @Field("refresh_token") String refreshToken);
和可观察到的

/**
 * 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());
}
然后在我的主要活动中,我订阅该行为主题并解析错误

SomeApi.getErrorEvent().subscribe(
            (e) -> {
                //parse the error
            }
    );

但是我不能重复对抛出错误的可观察对象的调用。

您需要使用操作符,更好地解释为:

下一步将继续( ) 在你的情况下,我会这样说:

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);
            }
        };
    }
private Func1
@Override
公共可观察消息(字符串accountId,int messageType){
返回mMessageService.getLikeMessages(messageType)
.onErrorResumeNext(mTokenTrick)。
refreshTokenAndRetry(mMessageService.getLikeMessages(messageType));
}

你能展示一下你现在如何将
refreshToken()
observable与其他调用联系起来吗?在上面的回答中,我想使用
defer()
操作符来避免用旧的observable重新尝试请求。代码:
onErrorResumeNext(refreshTokenAndRetry(observable.defer(()->userApi.getCurrentUser()))
。希望对某人有用:)@blizzard谢谢你的评论。事实证明,对我来说,你的建议非常重要
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);
            }
        };
    }
@Override
public Observable<List<MessageEntity>> messages(String accountId, int messageType) {
    return mMessageService.getLikeMessages(messageType)
            .onErrorResumeNext(mTokenTrick.
                    refreshTokenAndRetry(mMessageService.getLikeMessages(messageType)));
}