Reputation: 533
Imagine I have a service to retrieve some authors (id, firstname, lastname, birthday, nationality) and a second service to retrieve an author's book (title, summary, number of pages). I would like my network call to return me a list of authors with their books.
To illustrate, my services would return me AuthorOResponse and BookResponse and I would like to emit an Observable of AuthorObject.
public class AuthorResponse {
private String id;
private String firstname;
private String lastname;
private Date birthday;
private String nationality;
}
public class BookResponse {
private String title;
private String summary;
private int pageNumber;
}
public class AuthorObject {
private String id;
private String firstname;
private String lastname;
private Date birthday;
private String nationality;
private List<BookObject> books
}
My services would be something like
Observable<List<AuthorResponse>> getAuthors()
Observable<List<BookResponse>> getAuthorBooks(String authorId)
I would like to use them to emit an Observable but cannot figure out how to do it since each of my calls to getAuthorBooks need an author.
I came up with something looking like this but I have an issue since my concatMap make me "loose" my author.
myServices.getAuthors()
.map(author -> createAuthor())
.concatMap(author -> mWebService.getAuthorBooks(author.getId())
.flatMapIterable(data -> data.items)
.map(book -> addBook())
Does someone know how I could do this ?
Upvotes: 1
Views: 2643
Reputation: 11058
You could use special flatMap
overload designed for such cases:
myServices.getAuthors()
.map(author -> createAuthor())
.flatMap(author -> mWebService.getAuthorBooks(author.getId()),
(author, data) -> {
author.setBooks(data.items));
return Observable.just(author);
})
.toList() //here is your Observable<List<Author>>
Upvotes: 6
Reputation: 10267
Maybe something like this:
getAuthors.map(new Func1<List<AuthorResponse>, AuthorObject>() {
@Override
public AuthorObject call(List<AuthorResponse> authorResponses) {
return createAuthor();
}
}).flatMap(new Func1<AuthorObject, Observable<AuthorObject>>() {
@Override
public Observable<AuthorObject> call(final AuthorObject authorObject) {
return getAuthorBooks(authorObject.id)
.map(new Func1<List<BookResponse>, AuthorObject>() {
@Override
public AuthorObject call(List<BookResponse> bookResponses) {
authorObject.books = parseBooks(bookResponses);
return authorObject;
}
});
}
});
Query the Authors, map each AuthorResponse
to AuthorObject
, then using flatMap
query books for each Author
, and map
it in order to add parsed books to the generated earlier AuthorObject
.
at the end you'll get an Observable
that emits AuthorObject
with their books list populated.
Upvotes: 2