我在我的Android应用程序中使用Retrofit进行网络调用。现在如果响应有问题(可能是错误的数据),我不希望执行onComplete。请参阅代码段,
restClient.getService().getProjectDetail(projectId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableObserver<List<Project>>() {
@Override
public void onNext(List<Project> value) {
/*Something wrong in the data and I would like to execute onError*/
}
@Override
public void onError(Throwable e) {
handleError(e, 0, "");
hideProgressDialog();
}
@Override
public void onComplete() {
hideProgressDialog();
}
});
提前致谢。
答案 0 :(得分:2)
由于您的最终消费者可能会崩溃,因此直截了当的方法是捕获该异常并委托给onError
:
.subscribeWith(new DisposableObserver<List<Project>>() {
@Override
public void onNext(List<Project> value) {
try {
// something that can crash
} catch (Throwable ex) {
// tell the upstream we can't accept any more data
dispose();
// do the error handling
onError(ex);
}
}
@Override
public void onError(Throwable e) {
handleError(e, 0, "");
hideProgressDialog();
}
@Override
public void onComplete() {
hideProgressDialog();
}
});
另一方面,RxJava在处理可能失败的用户函数时会在自己的运算符中执行pretty much this:try-catch,cancel the source并通过onError
发出信号。
答案 1 :(得分:0)
您可以使用flatMap。例如:
restClient.getService().getProjectDetail(projectId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.flatMap(new Function<Integer, Observable<List<Project>>>() {
@Override
public Observable<List<Project>> apply(List<Project> x) {
if(validate(x)){
return Observable.error(new Exception("Response is invalid"));
}else {
return Observable.just(x);
}
}
public boolean validate(List<Project> x){
return x.size()==0;
}
})
.subscribeWith(new DisposableObserver<List<Project>>() {
@Override
public void onNext(List<Project> value) {
/*Something wrong in the data and I would like to execute onError*/
}
@Override
public void onError(Throwable e) {
handleError(e, 0, "");
hideProgressDialog();
}
@Override
public void onComplete() {
hideProgressDialog();
}
});
示例其他:
Observable.just(1)
.flatMap(new Function<Integer, Observable<Integer>>() {
@Override
public Observable<Integer> apply(Integer x) {
if(validate(x)){
return Observable.error(new Exception("Response is invalid"));
}else {
return Observable.just(x);
}
}
public boolean validate(Integer x){
return x==1;
}
})
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onComplete() {
}
@Override
public void onError(Throwable e) {
Log.e("ERROR", e.getMessage());
}
@Override
public void onNext(Integer integer) {
Log.d("flatMap", "onNext: " + integer.toString());
}
});
答案 2 :(得分:0)
您正在质疑rx-java的基本行为。如果你只想调用hideProgressDialog一次。你应该从onError中删除它。问题之后,序列必须消灭。
但是如果你想在onNext中获取其他项目并避免onError,你可以在你的可观察链上使用这个方法:onErrorResumeNext
restClient.getService().getProjectDetail(projectId).onErrorResumeNext(/*Func1*/)
考虑此方法将在onNext中发出List<Project>
而不是onError。和onComplete不会调用
只要你使用改造,onNext只会调用一次。所以更好的解决方案是第一个