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

标签 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);
}

这是处理问题的标准方法吗?如何将一个可观察值包装在另一个可观察值中?谁能指导一下吗?

最佳答案

响应式扩展的惯用方式是使用组合,这是 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();

关于java - 如何在 RxJava 中将 observable 包装在另一个 observable 中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44671161/

相关文章:

java - 在 eclipse indigo 中找不到 Window builder pro

java - 使用装饰器模式而不添加 "different"行为

android - Flutter:如果页面已经被压入堆栈,如何重新打开它们?

java - 如何启用/禁用 ToggleButton 的声音?

android - 可观察的 zip 顺序

java - Oracle 数据类型 raw 的等效 java 类型是什么?

java - 如何从java代码调用外部dll函数

android - 电池管理器中android EXTRA_SCALE和LEVEL的单位

android - 如何使用 MVP 和 rxjava 构建我的应用程序并进行改造以从 Observables 中获取数据?

android - 使用 RxJava 链接 Retrofit 调用并返回主对象