Amio.io
Amio.io

Reputation: 21595

Call service only if preceding observable succeeded

Background

I am just diving into the concept of RX for java. Frankly, I don't get it. In my project I use retrofit library for calling services. Currently, I have implemented all the services using callback. If I want to orchestrate service calls I have to call callbacks in callbacks which leads to quite a confusing code.

Problem

For the following two services I would like to call service B iff service A completed successfully using the Observables approach.

public interface RetrofitRestService {

    @GET("...")
    Observable<Object> A();

    @GET("...")
    Observable<Object> B();
}

I was searching for Observable operators I could use for my task but without any luck. I can imagine an operator like this:

RetrofitRestServices service;
service.A().ifSuccessfull(B());

//OR
service.A().ifWasNotEmpty(B());

//OR
service.A().useCondition(new Condition(){ ... }, B());

Upvotes: 2

Views: 2003

Answers (2)

dwursteisen
dwursteisen

Reputation: 11515

If you want to call A, then call B, you can use the operator concat : B will be called if A is completed.

service.A().concatWith(service.B()).subscribe();

But if A return null, B will be called.

If it's the case, then this anwser will be better : https://stackoverflow.com/a/28685808/476690

EDIT after comment

If you want to use the result of A() then flatMap operator is what you need

service.A().flatMap(resultOfA -> service.B(resultOfA)).subscribe();

(giving resultOfA as an argument of B() is just an example of use)

Another way :

You can build a result too from the response of A, and the response of B

service.A().flatMap(resultOfA -> service.B().zipWith(Observable.just(resultOfA), (a, b) -> new ResultOf(a, b))).subscribe();

zipoperator will build a result with the result of A and B, in this case. ResultOf is just an example class to show how to build a result with the result of A and B.

More info on flapMap : When do you use map vs flatMap in RxJava?

Upvotes: 3

meddle
meddle

Reputation: 159

What about this:

service.A().isEmpty().filter(new Func1<Boolean, Boolean>() {
    @Override
    public Boolean call(Boolean empty) {
        return !empty;
    }
})
.flatMap(new Func1<Boolean, Observable<? extends Object>>() {
    @Override
    public Observable<? extends Integer> call(Boolean empty) {
        return B();
    }
});

The isEmpty operator will emit a boolean value, which will be true only if A() doesn't emit anything. That's why if A() emits an item, the filter checking if the result of isEmpty will pass and the flatMap will be invoked, thus invoking B().

Upvotes: 1

Related Questions