Java – RxJava – Checks the condition and repeats only once if the condition is true

RxJava – Checks the condition and repeats only once if the condition is true… here is a solution to the problem.

RxJava – Checks the condition and repeats only once if the condition is true

I use RxJava + Retrofit to make API calls in my Android application. There may be situations where a user makes a request and his token has expired. In this case, I get a normal response in onNext, but the response does not contain a result, but instead contains some error elements of code. If this happens, I need to log in the user back and repeat the original request only after I get a new token.
So I want to use RxJava to organize this.
To make things easier, I’ll give a simple example. Let’s say I have the following method:

public void test(int someInt){
    Observable.just(someInt)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<Integer>() {
                @Override
                public void onCompleted() {
                    log("onCompleted");
                }

@Override
                public void onError(Throwable e) {
                    e.printStackTrace();
                    log("onError");
                }

@Override
                public void onNext(Integer integer) {
                    log("onNext - " + integer);
                }
            });

I want to check if (someInt == 0) before onNext() is called. If I get false, I want to go ahead and call onNext(), but if I get true, I want to do something and repeat the original can only be observed once, and if the condition returns false the second time I don’t want to repeat again.

Can someone help me figure out what options I have for this?
P.S. I’m new to the RX world.

Solution

Here you go. Because you want to retry the entire chain, .retryWhen is perfect for it, so you have to “play with” the error a bit.

Below if you detect an invalid token and you pass an error (only the first time), retryWhen will capture and resubscribe the entire rx chain (from Observable.just(someInt)

).

 haveRetriedOnce = false;

Observable.just(someInt)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .flatMap(integer ->{
          if(integer == 0){
            if(haveRetriedOnce){
               return Observable.error(new UserOperationException());
            }
             problem, throw an error and the .retryWhen will catch it
            return Observable.error(new InvalidTokenException());
          }else{
            return Observable.just(integer);
          }
        })
        .retryWhen(observable -> observable.flatMap(throwable->{
          if(throwable instanceOf InvalidTokenException){
            haveRetriedOnce = true;
            return just(0);  retry, the int here is irrelevant
          }else{
             other error, pass it further
            return Observable.error(throwable);
          }
        }))
        .subscribe(new Subscriber<Integer>() {
            @Override
            public void onCompleted() {
                log("onCompleted");
            }

@Override
            public void onError(Throwable e) {
                e.printStackTrace();
                log("onError");
            }

@Override
            public void onNext(Integer integer) {
                log("onNext - " + integer);
            }
        }

Related Problems and Solutions