I'm playing around with RXJava, retrofit in Android. I'm trying to accomplish the following:
I need to poll periodically a call that give me a Observable> (From here I could did it)
Once I get this list I want to iterate in each Delivery and call another methods that will give me the ETA (so just more info) I want to attach this new info into the delivery and give back the full list with the extra information attached to each item.
I know how to do that without rxjava once I get the list, but I would like to practice.
This is my code so far:
pollDeliveries = Observable.interval(POLLING_INTERVAL, TimeUnit.SECONDS, Schedulers.from(AsyncTask.THREAD_POOL_EXECUTOR))
.map(tick -> RestClient.getInstance().getApiService().getDeliveries())
.doOnError(err -> Log.e("MPB", "Error retrieving messages" + err))
.retry()
.subscribe(deliveries -> {
MainApp.getEventBus().postSticky(deliveries);
});
This is giving me a list of deliveries. Now I would like to accomplish the second part.
Hope I been enough clear. Thanks
Finally I found a nice way to do it.
private void startPolling() {
pollDeliveries = Observable.interval(POLLING_INTERVAL, TimeUnit.SECONDS, Schedulers.from(AsyncTask.THREAD_POOL_EXECUTOR))
.flatMap(tick -> getDeliveriesObs())
.doOnError(err -> Log.e("MPB", "Error retrieving messages" + err))
.retry()
.subscribe(this::parseDeliveries, Throwable::printStackTrace);
}
private Observable<List<Delivery>> getDeliveriesObs() {
return RestClient.getInstance().getApiService().getDeliveries()
.flatMap(Observable::from)
.flatMap(this::getETAForDelivery)
.toSortedList((d1, d2) -> {
if (d1.getEta() == null) {
return -1;
}
if (d2.getEta() == null) {
return 1;
}
return d1.getEta().getDuration().getValue() > d2.getEta().getDuration().getValue() ? 1 : -1;
});
}
Let's go step by step.
It's working properly and it's quite nice, I'm starting to like rxjava :)
I haven't spent a lot of time with Java 8 lambdas, but here's an example of mapping each object to a different object, then getting a List<...>
out at the other end in plain ol' Java 7:
List<Delivery> deliveries = ...;
Observable.from(deliveries).flatMap(new Func1<Delivery, Observable<ETA>>() {
@Override
public Observable<ETA> call(Delivery delivery) {
// Convert delivery to ETA...
return someEta;
}
})
.toList().subscribe(new Action1<List<ETA>>() {
@Override
public void call(List<ETA> etas) {
}
});
Of course, it'd be nice to take the Retrofit response (presumably an Observable<List<Delivery>>
?) and just observe each of those. For that we ideally use something like flatten()
, which doesn't appear to be coming to RxJava anytime soon.
To do that, you can instead do something like this (much nicer with lambdas). You'd replace Observable.from(deliveries)
in the above example with the following:
apiService.getDeliveries().flatMap(new Func1<List<Delivery>, Observable<Delivery>>() {
@Override
public Observable<Delivery> call(List<Delivery> deliveries) {
return Observable.from(deliveries);
}
}).flatMap(...)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With