定期轮询以固定间隔轮询到后端API一定次数 - 改造& RxJava

时间:2017-07-05 08:27:58

标签: android retrofit2 rx-java2

我希望以预定义的定期间隔轮询后端呼叫一定次数。如果我在循环之间收到预期的有效负载并更新UI,我想退出循环,否则终止轮询。

以下是我在进行标准http呼叫时通常会执行的代码。

//Response Model from backend API
public class ApplicationStatusResponse
{
public boolean isActive;
}

//Retrofit facade  
@POST(v1/api/applicationStatus)
Single<ApplicationStatusResponse> checkApplicationStatus(@Body ApplicationStatusRequest applicationRequest);


-----

DisposableSingleObserver<ApplicationStatusResponse> disposableSingleObserver = new DisposableSingleObserver<ApplicationStatusResponse>() {
    @Override
    public void onSuccess(ApplicationStatusResponse response) {
            // Update UI Here
    }

    @Override
    public void onError(Throwable e) {

    }
};

CompositeDisposable compositeDisposable = new CompositeDisposable();

// Following call works alaways works 
DisposableSingleObserver<ApplicationStatusResponse> disposable = originationRepo.checkApplicationStatus(applicationStatusRequest)
        .observeOn(schedulerProvider.mainThread())
        .subscribeWith(disposableSingleObserver);

compositeDisposable.add(disposable);

但是我在下面的代码中丢失了语法错误,并且在从Flowable.interval调用时我无法使用相同的disposableSingleObserver并需要帮助我的用例我需要更新UI定期状态,直到时间过去或状态有效,这是首先发生的,如果我收到HTTP状态代码500而不是重复,直到满足上述条件,我也不会终止轮询。

 //Help Needed here  when I need polling in regular interval - I am kind of the syntax error complain from Android Studio

int INITIAL_DELAY = 0;
int POLLING_INTERVAL = 1000;
int POLL_COUNT = 8;

disposable = Flowable
            .interval(INITIAL_DELAY, POLLING_INTERVAL, TimeUnit.MILLISECONDS)
            .map(x -> originationRepo.checkApplicationStatus(applicationStatusRequest))
            .take(POLL_COUNT) ??
            // How can I receive the response payload and update the UI

compositeDisposable.add(disposable);

提前感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

选项#1 使用filter + take(1)

disposable = Flowable
            .interval(INITIAL_DELAY, POLLING_INTERVAL, TimeUnit.MILLISECONDS)
            .map(x -> originationRepo.checkApplicationStatus(applicationStatusRequest))
            .take(POLL_COUNT) //YES
            .doOnNext() // update UI here
            .map(response -> ) // should stop condition. true - stop, false - continue
            .filter(!shouldContinue)
            .take(1)

选项#2 使用Subject + takeUntil

Subject<Boolean> stopSubject = PublishSubject.create();
disposable = Flowable
            .interval(INITIAL_DELAY, POLLING_INTERVAL, TimeUnit.MILLISECONDS)
            .takeUntil(stopSubject.asObservable())
            .map(x -> originationRepo.checkApplicationStatus(applicationStatusRequest))
            .take(POLL_COUNT) //YES
            .subscribe(
                response -> {
                    //update UI
                    boolean shouldStop = ... // calculate
                    if (shouldStop) {
                        stopSubject.onNext(true);
                    }
                }
            ...
             )

PS。这是伪代码。我希望你能有所了解。

答案 1 :(得分:2)

(继续MyDogTom's answer你也可以通过抛出自定义错误/异常来“短路”observable)

选项3:

disposable = Flowable
        .interval(INITIAL_DELAY, POLLING_INTERVAL, TimeUnit.MILLISECONDS)
        .map(x -> originationRepo.checkApplicationStatus(applicationStatusRequest)) // .flatMap (?)
        .take(POLL_COUNT) //YES
        .doOnNext() // update UI here
        .map(response -> {
           if(!response.checkCondition()) {
             throw new ShortCircuitException();
           }
             return response.data();
        })
        .onErrorResumeNext(throwable -> (throwable instanceof ShortCircuitException)
            ? Observable.empty()
            : Observable.error(throwable))