shadox
shadox

Reputation: 3779

Emit Observable only after second Observable is received

I'm using Rx for calling our API with Retrofit. At some point I need to call our API, wait for response 1, extract some metadata from it and then call API again waiting for response 2. After I have response 2 I can emit my Observable. My problem is, I don't know how to: Make a call 2 and emit only after I have response 2

Here are my functions from the class that should emit Model Observable. Method get2 doesn't have to be visible for outside world.

public Observable<Model> get1(String slug) {
    return api1
            .getInfo(slug)
            .subscribeOn(Schedulers.io())
            .map(resonse1 -> {
                String metadata = response1.getMetadata();

                //Make call2 with metadata
                //call(2)

                Model model = response1.getModel();
                model.setInfo(/*Info from call2*/) 

                return model;
            })
            .observeOn(AndroidSchedulers.mainThread());
}


private Observable<Info> get2(String metadata) {
    return api2.getInfo(new InfoAsset(metadata))
            .subscribeOn(Schedulers.io())
            .map(response2 -> {
                return response2.getInfo;
            })
            .observeOn(AndroidSchedulers.mainThread());
}

Upvotes: 2

Views: 100

Answers (2)

Tassos Bassoukos
Tassos Bassoukos

Reputation: 16152

Use nested flatMaps, and don't use observeOn unless you want to do thread hopping:

private Observable<Info> get2(String metadata) {
    return api2.getInfo(new InfoAsset(metadata))
        .subscribeOn(Schedulers.io())
        .map(response2 -> {
            return response2.getInfo;
        });
        // no ObserveOn here.
} 

public Observable<Model> get1(String slug) {
    return api1
        .getInfo(slug)
        .subscribeOn(Schedulers.io())
        .flatMap (response1 -> {
            Model model = response1.getModel();
            return get2(response1.getMetadata())
                   .map(response2 -> {
                        model.setInfo(response2); 
                        return model;
                   });
        );
    });
}

Upvotes: 1

Dave Moten
Dave Moten

Reputation: 12097

Instead of map use flatMap:

.flatMap(response1 -> {
            String metadata = response1.getMetadata();
            return get2(metadata)
              .map(info -> {
                     Model model = response1.getModel();
                     model.setInfo(info); 
                     return model;
                   });
         })
...

Be careful though because you are using mutable objects across threads so you may have visibility problems. Consider using immutable objects or ensure changes are synchronized.

Upvotes: 2

Related Questions