【问题标题】:How to not repeat the same operations in RxJava?如何不在 RxJava 中重复相同的操作?
【发布时间】:2018-11-20 08:22:51
【问题描述】:

我有如下代码:

authRepository.login(userName, password)
              .doOnSubscribe(__ -> apiProgress.setValue(ApiProgress.start()))
              .doFinally(() -> apiProgress.setValue(ApiProgress.stop()))
              .subscribe(login -> loginData.setValue(login), 
                           err -> apiError.setValue(ApiError.create(err)))

我需要对所有 api 调用重复 doOnSubscribe(..)doFinally

有没有办法实现这个东西?

【问题讨论】:

    标签: java android rx-java rx-android


    【解决方案1】:

    欢迎来到 StackOverflow! https://stackoverflow.com/conduct

    您可以使用Transformer (http://reactivex.io/RxJava/javadoc/rx/Single.Transformer.html) 创建类似的内容

    static <T> SingleTransformer<T, T> subscribeAndFinalTransformer() {
            return new SingleTransformer<T, T>() {
                @Override
                public SingleSource<T> apply(Single<T> upstream) {
                    return upstream.doOnSubscribe(disposable -> {
                        // Your doOnSubscribe Block
                    }).doFinally(() -> {
                        // Your doFinally Block 
                    });
                }
            };
        }
    

    及以上可重复使用的Transformer 可以使用compose 方法为所有Single 附加。

    authRepository.login(userName, password).compose(subscribeAndFinalTransformer())
    .subscribe()
    
    authRepository.anotherApi().compose(subscribeAndFinalTransformer()).subscribe()
    

    如果您使用ObservableCompletable,则应使用等效的Transformer 而不是SingleTransformer

    编辑:

    如果您只想对某些调用重复使用某些操作,则上述方法很方便。

    如果您想将操作附加到所有 API 调用,您可以创建 Retrofit CallAdapter

    class RxStreamAdapter implements CallAdapter {
    
        private final Class rawType;
        private final CallAdapter<Object, Object> nextAdapter;
        private final Type returnType;
    
        RxStreamAdapter(Class rawType,
                        Type returnType,
                        CallAdapter nextAdapter) {
            this.rawType = rawType;
            this.returnType = returnType;
            this.nextAdapter = nextAdapter;
        }
    
        @Override
        public Type responseType() {
            return nextAdapter.responseType();
        }
    
        @Override
        public Object adapt(Call call) {
            if (rawType == Single.class) {
                return ((Single) nextAdapter.adapt(call))
                        .doOnSubscribe(getDoOnSubscribe())
                        .doFinally(getDoFinally());
            } else if (returnType == Completable.class) {
                return ((Completable) nextAdapter.adapt(call))
                        .doOnSubscribe(getDoOnSubscribe())
                        .doFinally(getDoFinally());
            } else {
                // Observable
                return ((Observable<Object>) nextAdapter.adapt(call))
                        .doOnSubscribe(getDoOnSubscribe())
                        .doFinally(getDoFinally());
            }
        }
    
        @NotNull
        private Consumer<Disposable> getDoOnSubscribe() {
            return disposable -> {
    
            };
        }
    
        @NotNull
        private Action getDoFinally() {
            return () -> {
    
            };
        }
    }
    

    然后在创建Retrofit Object时添加(RxJava2CallAdapterFactory之前)

    RetrofitApi retrofitApi = new Retrofit
                    .Builder()
                    .addCallAdapterFactory(new CallAdapter.Factory() {
                        @Override
                        public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
                            CallAdapter<?, ?> nextAdapter = retrofit.nextCallAdapter(this, returnType, annotations);
                            Class<?> rawType = getRawType(returnType);
                            if (rawType == Single.class || rawType == Observable.class || rawType == Completable.class) {
                                return new RxStreamAdapter(getRawType(returnType), returnType, nextAdapter);
                            } else {
                                return nextAdapter;
                            }
                        }
                    })
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .build()
    

    您还可以使用RxJavaPlugins 设置挂钩。但是你无法区分黑白正常流和改造流。

    希望对你有帮助!

    【讨论】:

    • 感谢您的回答。它确实在一定程度上解决了问题,但现在我每次调用 api 时都需要调用compose(subscribeAndFinalTransformer())。有没有其他选择?
    • 顺便说一句,你提供了问题的答案,所以我接受你的解决方案:)。
    • @VatishSharma 我希望你正在使用改造。我已经更新了答案。由于灵活性,我仍然会使用compose() 而不是CallAdapter。同样,在某些情况下,您必须使用 Adapter 方法,例如其他开发人员可能忘记附加每次调用所需的操作。在这种情况下,它会有所帮助。干杯!
    • 太棒了!谢谢,这正是我想要实现的。
    猜你喜欢
    • 2017-03-31
    • 1970-01-01
    • 1970-01-01
    • 2019-01-03
    • 1970-01-01
    • 2016-12-13
    • 2019-10-18
    • 1970-01-01
    • 2016-03-19
    相关资源
    最近更新 更多