I use RxJava + Retrofit
to make API calls in my Android app. There may be cases when user makes a request and his token is expired. In this cases I receive a normal response in my onNext
, but the response contains not the result but an error element with some code. If such thing happens I need to re-login the user and only after getting a new token repeat the original request.
So I want to organize this using RxJava
.
To make things easier I will bring 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 continue and get onNext()
called, but if I get true
I want to perform some action and repeat the original observable only once, if the condition returns false second time I don't want to repeat again.
Can someone help me to figure out what options do I have for this? P.S. I am new in RX world.
Here you go. Since you want to retry the whole chain .retryWhen is great for it so you have to "play" a bit with the errors.
Below if you detect a invalid token, you pass an error (only on the first time) which the retryWhen will catch and resubscribe to the whole rx chain (starting 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);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With