André Delgado
André Delgado

Reputation: 85

Wait for location and then execute retrofit call with rxjava

In my application I need to wait for the user location then execute a retrofit (when location is received).

I have the observable working

mlocationService.getLocation()
            .timeout(LOCATION_TIMEOUT_SECONDS, TimeUnit.SECONDS)
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(location -> {
                Log.d(TAG, "COORDS: " + location.getLatitude() + ", " + location.getLongitude());
            }, e -> Log.e(TAG, e.getMessage()));

But now I need to call the second observable with the retrofit call, is there a better way than nesting the second observable inside the onNext() of the first one?

Thank you

Upvotes: 1

Views: 700

Answers (1)

Jahnold
Jahnold

Reputation: 7683

Yes you can use the flatmap operator:

mlocationService.getLocation()
        .timeout(LOCATION_TIMEOUT_SECONDS, TimeUnit.SECONDS)
        .subscribeOn(Schedulers.newThread())
        .flatmap(location -> retrofitApi.getData(location))
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(...)

The subscription will now get the result of the retrofit call

If you need to return both the retrofit result and the location then you can use the zip operator:

mlocationService.getLocation()
        .timeout(LOCATION_TIMEOUT_SECONDS, TimeUnit.SECONDS)
        .subscribeOn(Schedulers.newThread())
        .flatmap(location -> Observable.zip(
            retrofitApi.getData(location),
            Observable.just(location),
            (Func2<Response<Data>, Location, ResponseLocation>) (response, location) -> {
                return new ResponseLocation(response, location)
            }
        ))
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(...)

Where ResponseLocation is just a class which takes a location and a retrofit result. The subscription would then get a ResponseLocation as it's argument.

EDIT

To use the location before you call Retrofit just expand the lambda:

mlocationService.getLocation()
        .timeout(LOCATION_TIMEOUT_SECONDS, TimeUnit.SECONDS)
        .subscribeOn(Schedulers.newThread())
        .flatmap(location -> {
            updateMap(location);
            return retrofitApi.getData(location);
        })
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(...)

Upvotes: 4

Related Questions