如何使用RxJava / RxAndroid在OnNext中抛出异常

时间:2018-01-15 01:02:42

标签: java android rx-java rx-android

我在我的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();
                    }
                });

提前致谢。

3 个答案:

答案 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只会调用一次。所以更好的解决方案是第一个