我正在使用RxJava和Reformation2(以OkHttp作为HTTP客户端(进行网络连接,并试图了解Reformation 2如何处理不同的错误,以及它们在RxJava方面的外观。以下代码说明了网络调用的RxJava Subscriber回调(使用Reform进行(。
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来确定原因?
从Reform源代码来看,似乎只有IOException和HttpException是可以看到的Throwables。有人能证实这是真的吗?
以下是基本信息:如果:,将调用onError()
- 您订阅的
observable
引发异常(例如,您在尝试读取文件时获得IOException
( - 则在
onNext()
方法中引发异常
如果您的onComplete()
中有异常,RxJava
将传播一个rx.exceptions.OnCompletedFailedException
,如果onError()
中有异常-您将获得rx.exceptions.OnErrorFailedException
。
也就是说,您可以在onError()
方法中探测收到的Throwable
,以查找您期望的异常。例如,您知道如果您的API调用导致客户端错误(4xx(,那么Reform将把它包装到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();
}
不要将onError
用于流。对于流量来说,这将和try-catch
一样糟糕。
错误HTTP代码是有效的响应,不应在onError
中处理它们。您可以在Result
中封装改装服务的返回类型,这使您能够在不引发异常的情况下获得有关调用发生的情况的信息。
您可以使用以下模式处理应用程序的状态:
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
来寻找我可能错过的东西。这是非常私人的,但我更喜欢快速而愤怒地崩溃,而不是在一段时间内处于未知状态,这将在以后更难调试的崩溃中表现出来。
在Kotlin中,我使用了如下
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)
}
}
})
)