如何将observable包装在RxJava中的另一个observable中?

时间:2017-06-21 08:50:25

标签: java android rx-java observable rx-android

我想用另一种方法包装改装api调用,我可以另外显示/隐藏加载器,检查网络等。当我的api返回可观察时,我最终的方式如下:

private <T> Observable<T> request(final Observable<T> apiCall, final ViewManager viewManager) {
    return Observable.create(new Action1<Emitter<T>>() {
        @Override
        public void call(final Emitter<T> emitter) {
            if (!NetworkUtils.isConnected(context)) {
                emitter.onError(new ConnectException("network not connected"));
                return;
            }
            viewManager.showLoader();
            apiCall.subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Observer<T>() {
                        @Override
                        public void onCompleted() {
                            viewManager.hideLoader();
                            emitter.onCompleted();
                        }

                        @Override
                        public void onError(Throwable e) {
                            viewManager.hideLoader();
                            emitter.onError(e);
                        }

                        @Override
                        public void onNext(T response) {
                            emitter.onNext(response);
                        }
                    });
        }
    }, Emitter.BackpressureMode.BUFFER);
}

这是处理问题的标准方法吗?如何将一个observable包装在另一个observable中?任何人都可以指导吗?

1 个答案:

答案 0 :(得分:2)

反应性扩展的惯用方法是使用组合,这是RX的强大功能之一。

首先让我们使用运算符定义所需的行为,你想要的是这样的:

apiCall
  .observeOn(AndroidSchedulers.mainThread())
  .startWith(Observable.defer(() -> {
      if (!NetworkUtils.isConnected(context)) {
          return Observable.error(new ConnectException("network not connected"));
      } else {
          return Observable.empty();
      }
  }))
  .doOnSubscribe(() -> viewManager.showLoader())
  .doOnCompleted(() -> viewManager.hideLoader())
  .doOnError(throwable -> viewManager.hideLoader());

现在,为了将其组合到任何网络apiCall Observable,您可以使用compose()运算符并将此逻辑封装到Transformer中:

class CustomTransformer<T> implements Observable.Transformer<T, T> {

    private final ViewManager viewManager;
    private final Context context;

    CustomTransformer(ViewManager viewManager, Context context) {
        this.viewManager = viewManager;
        this.context = context;
    }

    @Override
    public Observable<T> call(Observable<T> apiCall) {
        return apiCall
                .observeOn(AndroidSchedulers.mainThread())
                .startWith(Observable.defer(() -> {
                    if (!NetworkUtils.isConnected(context)) {
                        return Observable.error(new ConnectException("network not connected"));
                    } else {
                        return Observable.empty();
                    }
                }))
                .doOnSubscribe(() -> viewManager.showLoader())
                .doOnCompleted(() -> viewManager.hideLoader())
                .doOnError(throwable -> viewManager.hideLoader());
        ;
    }
}

然后您可以使用任何网络Observable撰写

someRetrofitQuery
   .compose(new CustomTransformer<>(viewManager, context))
    ...
   .subscribe();