Composing a network request with RX and Kotlin
I am working on an android app that uses kotlin with RXJava and Retrofit for network calls. When launched, the application will make several network calls to a REST-like backend. This procedure is very similar to the procedure used by Netflix in their examples. However, in trying to rewrite it to work with Kotlin I am struggling. I'm having trouble understanding how work comes back in Kotlin shutdown. It would be very helpful to help here!
Netflix example:
return getUser(userId).flatMap(user -> {
Observable<Map<String, Object>> catalog = getPersonalizedCatalog(user)
.flatMap(catalogList -> catalogList.videos().<Map<String, Object>> flatMap(
video -> {
Observable<Bookmark> bookmark = getBookmark(video);
Observable<Rating> rating = getRatings(video);
Observable<VideoMetadata> metadata = getVideoMetadata(video);
return Observable.zip(bookmark, rating, metadata, (b, r, m) -> combineVideoData(video, b, r, m));
}));
Observable<Map<String, Object>> social = getSocial(user).map(s -> {
return s.getDataAsMap();
});
return Observable.merge(catalog, social);
}).flatMap(data -> {
String json = SimpleJson.mapToJson(data);
return response.writeStringAndFlush("data: " + json + "\n");
});
My decision:
restClient.getVideoList("VAR1", "VAR2")
.subscribeOn(Schedulers.io())
.flatMap { videos -> Observable.from(videos)}
.map { video ->
var actors: Observable<List<Actor>> = restClient.getActorList(video.id(), "VAR2")
var price = restClient.getPrice(video.id(), "VAR2")
Observable.zip(actors, price, { (a, p) -> combineVideoData(video, a, p)})
}.map{ video -> doSomethingWithVideo(video) }
For some reason, my implementation is returning an observable, not a video object, which I should have. Surely there is something wrong with my understanding of closures in Kotlin and I have been trying to figure it out for days but still struggling. I would be very grateful for any help!
source to share
You created an observable but did not subscribe to it. You should use forEach {}
(from RxKotlin) or subscribe {}
instead of the latter map
. It will look like
restClient
.getVideoList("VAR1", "VAR2")
.subscribeOn(Schedulers.io())
.flatMap { videos -> Observable.from(videos)}
.map { video ->
var actors: Observable<List<Actor>> = restClient.getActorList(video.id(), "VAR2")
var price = restClient.getPrice(video.id(), "VAR2")
Observable.zip(actors, price, { (a, p) -> combineVideoData(video, a, p)})
}
.forEach { video -> doSomethingWithVideo(video) }
source to share