我正在努力在RxJava2中正确处理异常。我试图在OkHttp3
拦截器内刷新我的令牌,如下所示:
tokenRepository.refreshToken(authStateManager.current.refreshToken!!)
.doOnError {
Log.w(TAG, "Could not obtain new access token.")
authStateManager.signOut()
}
.subscribe { tokenResponse ->
Log.d(TAG, "Obtained new access token: " + tokenResponse.toString())
authStateManager.updateAfterTokenResponse(TokenResponse.jsonDeserialize(tokenResponse.toString()), null)
token = authStateManager.current.accessToken
}
如果刷新令牌有效并且请求返回200,它可以很好地工作。但是如果刷新令牌无效并且我得到一些错误代码(例如400),则执行doOnError
块但是它会继续到抛出以下异常的subscribe块:
retrofit2.adapter.rxjava2.HttpException: HTTP 400
at retrofit2.adapter.rxjava2.BodyObservable$BodyObserver.onNext(BodyObservable.java:54)
at retrofit2.adapter.rxjava2.BodyObservable$BodyObserver.onNext(BodyObservable.java:37)
...
我尝试使用onErrorReturn
和onErrorResumeNext
,但我想完全跳过订阅块(它有一个错误,只是记录用户并且不要尝试做任何事情)。可能吗? refreshToken
方法返回Single<JsonObject>
类型的响应。
答案 0 :(得分:3)
您不能在订阅中使用onError
吗?我喜欢使用RxKotlin。例如,我可以执行以下操作:
.subscribeBy(onSuccess = {
// do Something in on success
}, onError = {
// do something in onError
})
所以在你的情况下,它可能是这样的:
tokenRepository.refreshToken(authStateManager.current.refreshToken!!)
.subscribeBy(onSuccess = {
Log.d(TAG, "Obtained new access token: " + it.toString())
authStateManager.updateAfterTokenResponse(TokenResponse.jsonDeserialize(it.toString()), null)
token = authStateManager.current.accessToken
}, onError = {
Log.w(TAG, "Could not obtain new access token.")
// the variable "it" here is a throwable which means you can determine if it's a RetrofitException and what status code is returned
})
但是,如果你不想使用RxKotlin,你可以在Kotlin处理你的Rx订阅:
.subscribe({ Log.d(TAG, "Obtained new access token: " + it.toString()) },
{ Log.e(TAG, "Error is ${it.message}") })
您可以在正在使用Log.e
的函数的第二部分中处理错误。
答案 1 :(得分:0)
我遇到了同样的问题但我现在修好了。我不知道我的解释是否正确,但似乎doOnError
没有处理异常。
您需要使用subscribe()
onError
作为参数的Consumer
方法,并在那里处理错误:
subscribe(Consumer<? super T> onSuccess, Consumer<? super Throwable> onError)
在Java中它看起来像这样:
.subscribe(tokenResponse -> {
Log.d(TAG, "Obtained new access token: " + tokenResponse.toString());
authStateManager.updateAfterTokenResponse(TokenResponse.jsonDeserialize(tokenResponse.toString()), null);
token = authStateManager.current.accessToken;
}, throwable -> {
Log.w(TAG, "Could not obtain new access token.");
authStateManager.signOut();
}));