我正在使用RxJava和Retrofit2(使用OkHttp作为HTTP客户端)进行网络连接,并试图了解Retrofit2如何处理不同的错误以及它们从RxJava方面的外观。以下代码说明了网络调用的RxJava订阅者回调(使用Retrofit进行)。
Subscription subscription = observable
.subscribeOn(mScheduler)
.observeOn(mAndroidScheduler)
.subscribe(new Subscriber<User>() {
@Override
public void onCompleted() {
Timber.d("onCompleted called");
mRetainerView.clearUserObservable();
mActivityView.hideProgressBar();
mActivityView.enableUi();
}
@Override
public void onError(Throwable e) {
Timber.d("onError called");
Timber.d(e.toString());
mRetainerView.clearUserObservable();
mActivityView.hideProgressBar();
mActivityView.enableUi();
}
@Override
public void onNext(User user) {
Timber.d("onNext called");
mRetainerView.clearUserObservable();
mActivityView.hideProgressBar();
mActivityView.enableUi();
mActivityView.launchMainActivity();
}
});
我的问题是,在什么情况下会调用onError(),一旦调用它,我如何查询Throwable以确定原因?
从Retrofit源看,可能看到的唯一Throwable是IOException和HttpException。任何人都可以验证这是真的吗?
答案 0 :(得分:8)
以下是基础知识:onError()
将在以下情况下调用:
observable
会引发异常(例如,您在尝试阅读文件时获得IOException
)onNext()
方法引发了异常。如果onComplete()
中存在例外情况,则RxJava
会传播rx.exceptions.OnCompletedFailedException
,如果onError()
中存在例外情况,您将获得rx.exceptions.OnErrorFailedException
。
也就是说,您可以在Throwable
方法中探测您收到的onError()
您遇到的异常情况。例如,您知道如果您的API调用导致客户端错误(4xx),则Retrofit会将其包装到HttpException
中。如果请求超时,您将获得SocketTimeoutException
。这是一个粗略的例子:
@Override
public void onError(Throwable e) {
Timber.d("onError called");
Timber.d(e.toString());
handleError(e);
}
private handleError(Throwable throwable) {
if (throwable instanceof HttpException) {
HttpException httpException = (HttpException)throwable;
int statusCode = httpException.code();
// handle different HTTP error codes here (4xx)
} else if (throwable instanceof SocketTimeoutException) {
// handle timeout from Retrofit
} else if (throwable instanceof IOException) {
// file was not found, do something
} else {
// generic error handling
mRetainerView.clearUserObservable();
mActivityView.hideProgressBar();
mActivityView.enableUi();
}
答案 1 :(得分:0)
不要将onError
用于流量。这与流量try-catch
一样糟糕。
错误HTTP代码是有效的回复,您不应在onError
中处理它们。
您可以在Result
中包装Retrofit服务的返回类型,这样您就可以获得有关调用的信息而不会抛出异常的信息。
您可以使用以下模式处理应用的状态:
service.getSomething()
.map(r -> Model.success(r.response()))
.onErrorReturn(Model::error)
.observeOn(AndroidSchedulers.mainThread())
.startWith(Resource.loading())
.subscribe(r -> {
myProgressBar.setVisible(r.isLoading());
if (r.isSuccess()) {
handleSuccess(); // e.g. 400 is also success but needs handling
}
if (r.isError()) {
handleError();
}
}, OnErrorNotImplementedException::new);
了解我是如何尝试处理流中的所有可能状态的,并故意将OnErrorNotImplementedException
扔给我可能已经错过的内容。这是非常个人化的,但我喜欢速度快而且速度快,而不是暂时处于未知状态,之后将在崩溃中表现得更难调试。
答案 2 :(得分:0)
在科特林,我用过类似波纹管的东西。
disposable.add(apiService.getLogin_service(parment1,parment1)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(object : DisposableSingleObserver<Login_Reg_Data_Model>() {
override fun onSuccess(model: Login_Reg_Data_Model) {
//success
}
override fun onError(e: Throwable) {
if (e is HttpException) {
// We had non-200 http error
Log.e("time exceptionr******>",e.message)
} else if (e is SocketTimeoutException) {
//time exception
Log.e("time exception******>",e.message)
} else if (e is IOException) {
// A network error
Log.e("network error******>",e.message)
} else {
//unknown error
Log.e("unknown error******>",e.message)
}
}
})
)