Как не повторять одни и те же операции в RxJava? - PullRequest
0 голосов
/ 20 ноября 2018

У меня есть код, подобный следующему:

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)))

Мне нужно повторить doOnSubscribe(..) и doFinally для всех вызовов API.

Есть ли способ добиться этого?

1 Ответ

0 голосов
/ 20 ноября 2018

Добро пожаловать в 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 можно прикрепить для всех Single, используя compose method.

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

authRepository.anotherApi().compose(subscribeAndFinalTransformer()).subscribe()

если вы используете Observable или Completable, вам следует использовать эквивалент Transformer вместо SingleTransformer

EDIT:

Вышеуказанный подход удобен, если вы хотите повторно использовать некоторые действия только для определенных вызовов.

Если вы хотите присоединить действия ко всем вызовам 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 () -> {

        };
    }
}

И затем добавьте его при создании Модифицированного объекта (До 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. Но вы не можете различить ч / б обычный поток и ретрофитпоток.

Надеюсь, это поможет!

...