RxJava заставляет retryWhen() запускать метод onError()

У меня есть следующий класс с реализацией RxJava для загрузки двух ресурсов из API. Я делаю некоторые rx, чтобы позволить ему повторить попытку или повторить, когда он не соответствует требованиям API/соединения. Однако я не могу заставить retryWhen() срабатывать onError() после попытки более 3 раз.

ВОПРОС / ПОМОЩЬ

пожалуйста, просмотрите мой код и помогите мне решить эту проблему.

ПРИМЕЧАНИЕ

Я реализую Rx, прочитав эти две статьи. статья 1, статья 2

SplashPresenter.class

public class SplashPresenter implements SplashContract.Presenter {

    private static final String TAG = SplashPresenter.class.getName();
    private static final int RETRY_TIMEOUT = 10;
    private static final int STOP_RETRY_TIME = 3;
    private static final int START_RETRY_TIME = 1;


    private SplashContract.View mView;

    @Override
    public void init(SplashContract.View view) {
        this.mView = view;
    }

    @Override
    public void onResume() {

        GetRemoteReceiverRelationshipSpec relationSpec = new GetRemoteReceiverRelationshipSpec();
        GetRemoteIncompleteReasonSpec reasonSpec = new GetRemoteIncompleteReasonSpec();

        Observable<RepoResult<ArrayList<IncompleteReasonViewModel>>> queryReason =
                Repository.getInstance().query(reasonSpec);

        Repository.getInstance().query(relationSpec)
                .concatMap(result -> queryReason)
                .repeatWhen(complete -> complete
                        .zipWith(Observable.range(START_RETRY_TIME, STOP_RETRY_TIME), (v, i) -> i)
                        .flatMap(repeatCount -> {
                            Log.i(TAG, "Repeat attempt: " + repeatCount);
                            mView.showLoadingDialog();
                            return Observable.timer(RETRY_TIMEOUT,
                                    TimeUnit.SECONDS);
                        }))
                .takeUntil(RepoResult::isSuccess)
                .retryWhen(error -> error
                        .zipWith(Observable.range(START_RETRY_TIME, STOP_RETRY_TIME), (v, i) -> i)
                        .flatMap(retryCount -> {
                            Log.i(TAG, "Retry attempt: " + retryCount);
                            mView.showLoadingDialog();
                            if (mView.getCommunicator() != null) {
                                mView.getCommunicator().onConnectionFail(retryCount);
                            }
                            return Observable.timer(RETRY_TIMEOUT,
                                    TimeUnit.SECONDS);
                        }))
                .filter(RepoResult::isSuccess)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(
                        result -> Log.i(TAG, "onNext()"),
                        err -> {
                            Log.i(TAG, "onError()");
                            if (mView.getCommunicator() != null) {
                                mView.dismissLoadingDialog();
                                mView.getCommunicator().onSplashScreeDismissError();
                            }
                        },
                        () -> {
                            Log.i(TAG, "onComplete()");
                            if (mView.getCommunicator() != null) {
                                mView.dismissLoadingDialog();
                                mView.getCommunicator().onSplashScreenSuccessDismiss();
                            }
                        }
                );
    }

    @Override
    public void onPause() {

    }
}

person Jongz Puangput    schedule 30.09.2016    source источник


Ответы (3)


Когда я писал аналогичный код раньше, я вручную добавлял Observable.error() в flatMap

.flatMap(retryCount -> {
    if (retryCount >= STOP_RETRY_TIME) {
        return Observable.error(someException);
    }
    return Observable.timer(RETRY_TIMEOUT, TimeUnit.SECONDS);
 }))
person ytRino    schedule 30.09.2016
comment
@JongzPuangput привет, что случилось после этого. - person ytRino; 11.10.2016
comment
красивый! я счастлив здесь, что. - person ytRino; 12.10.2016

Чтобы сохранить бросок после повторной попытки (вместо создания пользовательского), верните Observable с соответствующей ошибкой из оператора zipWith, когда retryCount превышает указанный предел.

.retryWhen(error -> {
                Observable<Integer> range = Observable.range(START_RETRY_TIME, STOP_RETRY_TIME);
                Observable<Observable<Long>> zipWith = error.zipWith(range, (e, i) ->
                        i < STOP_RETRY_TIME ?
                                Observable.timer(i, TimeUnit.SECONDS) :
                                Observable.error(e));
                return Observable.merge(zipWith);
            });
person Matthew Mayaki    schedule 19.09.2017

Передайте счетчик повторных попыток и ошибку в объект Pair, если вы достигли предела повторных попыток, получите исключение из парного объекта и поднимите его.

source.retryWhen(errors -> errors
                        .zipWith(Observable.range(1, REQUEST_RETRY), Pair::new)
                        .flatMap(errPair -> {
                            int retryTime = errPair.second;
                            if (retryTime < REQUEST_RETRY) {
                                return Observable.timer(retryTime * RETRY_DELAY, TimeUnit.MILLISECONDS);
                            } else {
                                return Observable.error(errPair.first);
                            }
                        })
                        .doOnError(this::handleError));
person alizeyn    schedule 15.08.2019