Daniel Gomez Rico
Daniel Gomez Rico

Reputation: 15936

RXJava Android - Observable result needed to create another observable

I cant find a way to combine or chain a list of observables that it´s responses are prerequisites to other call that creates another Observable.

I´m using retrofit with observables.

My Service:

String url = "/geocode/json?sensor=false";

@GET(url)
Observable<GeocodeResult> getReverse(@Query("key") String gMapsKey,
                                     @Query("latlng") LatLng origin);

And another service needs that GeocodeResult

@POST("/api/orders")
Observable<Order> createOrder(@Body GeocodeResult newOrder);
  1. And I´m trying with:

    // Prerequisite 1 Observable geocodeObservable = Address.get(...);

    // Call createOrder after geocode is obtained? return Observable.combineLatest(geocodeObservable, geocode -> createOrder(geocode));

But it don´t work because combineLatest needs an object, not an observable but I need to return the observable.

With JoinObservable:

Pattern5<Geocode> pattern = JoinObservable.from(geocodeObservable)
Plan0<Observable<Order>> plan = pattern.then(Order::create);
return JoinObservable.when(plan).toObservable().toBlocking().single();

But it throws an NoSuchElementException exception. Why?

I do toBlocking().single() because I need the Observable and not the Observable<Observable<Order>> :(.

Or how can I do it?

Upvotes: 3

Views: 1931

Answers (2)

Daniel Gomez Rico
Daniel Gomez Rico

Reputation: 15936

I ended up creating a new Object and using Observable.combineLatest to combine all the prerequisites creating a new Observable and then using flatMap to create the new Observable from that observable.

Observable<NewOrderWrapper> newOrderObservable = Observable.combineLatest(prerequisites, (param1, param2,...) -> {return new NewOrderWrapper(param1, param2,...)});

and then

Observable<Order> finalOrderObservable = newOrderObservable.flatMap(newOrderWrapper -> create(newOrderWrapper))

Check a post here MakinGIANST/RXJava post.

Thanks to @LukaCiko

Upvotes: 2

LukaCiko
LukaCiko

Reputation: 4445

You could try using flatMap which can take the second observable as an parameter.

The function takes the items emitted by the first observable and creates an observable for each of those items and then flattens the items emitted by those observables into a single observable. This sounds complex, but fortunately both your Retrofit functions emit only a single item, so only one observable gets "flattened" into a observable.

You can use flatMap like this:

restApi.getReverse(gMapsKey, origin)
    .flatMap(geocodeResult -> createOrder(geocodeResult))
    .subscribe(order -> doSomething(order));

combineLatest doesn't really fit your needs, because it would perform both REST calls at the same time, not one after the other, so you can't use the response of the first one as the parameter of the second. I can't comment on why the exception gets thrown for JoinObservable because it's not a part of any public API. Also toBlocking() shouldn't really be used for anything other than testing.

Upvotes: 6

Related Questions