Reputation: 85
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
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