5
votes

I am trying to use retrofit +rxjava to make nested api calls. Basically I have to construct a List of Library objects. Each Library object has a list of Authors and each Author object has a list of Books. This is how my json is structured.

Library json -

{
 title: "Library",
 items: [
      {
        title: "Library1"
        image: "http://example.com/image/101/image_lib1.png"
        url: "http://example.com/api/1"
      },
      {
        title:"Library2"
        image: "http://example.com/image/101/image_lib2.png"
        url: "http://example.com/api/2"
      },
      {
        title:"Library3"
        image: "http://example.com/image/101/image_lib3.png"
        url: "http://example.com/api/3"
      }
   ]
 }

And Authors json-

{
 title: "Authors",
 items: [
      {
        title: "J.K Rowling"
        image: "http://example.com/image/101/image_author1.png"
        url: "http://example.com/api/101"
      },
      {
        title:"Mark Twain"
        image: "http://example.com/image/101/image_author2.png"
        url: "http://example.com/api/201"
      },
      {
        title:"Charles Dickens"
        image: "http://example.com/image/101/image_author3.png"
        url: "http://example.com/api/301"
      }
   ]
 }

And Books json-

{
description: Books,
imageurl: "http://example.com/image/101/image_101.png",
items: [
   {
     id: 101,
     title: "Oliver Twist ",
     description: "some description"
   },
  {
   id: 1011,
   title: "Hard times",
   description: "some more description."
  }
}
]
}

My api interface is given below.

  @GET("/api/")
  Observable<LibraryResponse> getLibraryList();

  @GET("/api/{feedId}")
  Observable<AuthorResponse> getAuthorList(@Path("feedId") String feedId);

  @GET("/api/{feedId}")
  Observable<BooksResponsee> getBooksList(@Path("feedId") String feedId);




Observable<List<Library>> observable = myRestInterface
    .getLibraryList()
    .map(a -> a.getItems())
    .flatMapIterable(b -> b)                 
    .flatMap(h -> myRestInterface                                                                 
                  .getAuthorList(h.getUrl().substring(h.getUrl().lastIndexOf("/") + 1))                                       
                  .map(x -> x.getItems())
                  .flatMapIterable(l -> l)
                  .flatMap(e -> myRestInterface
                                .getBooksList(e.getUrl().substring(e.getUrl().lastIndexOf("/") + 1))
                                .map(d -> d.getItems())
                                .flatMapIterable(c -> c)))

    .collect(// ? into list of main object)
    .doOnNext(mainObjectList -> new ViewupdateMethod(mainObjectList));
    .subscribe(...);

I am trying to construct one Librarylist object that I can use to update my UI. I am kind of stuck here. After making the multiple calls, how do I save the results back and collect everything to a list of library object?

1
May be you should try .toList() ? - Aleksandr
Why do you need to request authors and their books if you're only interested in libraries? If you need something like SQL join here, then you need to construct another class, LibraryWithAuthorsWithBooks - Kirill Gamazkov
@KirillGamazkov, My Library POJO contains List<Authors> and Author POJO contains LIst of Books. So I need to populate everything and get the Library object - Sammys
Please attach LibraryResponse#getItems(), AuthorResponse#getItems() and BookResponse#getItems() method signatures. If *Response.getItems() returns List<*Pojo>, then I wonder why your REST interface doesn't fill those lists with appropriate objects for you - Kirill Gamazkov
By the way, you can replace .map(a -> a.getItems()).flatMapIterable(b -> b) with .flatMapIterable(a -> a.getItems()) - Kirill Gamazkov

1 Answers

3
votes
    Observable<List<Library>> observable = myRestInterface
            .getLibraryList()
            .flatMapIterable(response -> response.getItems())
            .doOnNext(library -> myRestInterface
                    .getAuthorList(library.getUrl().substring(library.getUrl().lastIndexOf("/") + 1))
                    .flatMapIterable(response -> response.getItems())
                    .doOnNext(author -> library.getAuthors().add(author))
                    .doOnNext(
                            author -> myRestInterface
                                    .getBooksList(author.getUrl().substring(author.getUrl().lastIndexOf("/") + 1))
                                    .flatMapIterable(response -> response.getItems())
                                    .doOnNext(book -> author.getBooks().add(book))
                                    .subscribe()
                    )
                    .subscribe()
            )

            .doOnNext(mainObjectList -> new ViewupdateMethod(mainObjectList))
            .subscribe();

Note .subscribe() calls. They are used to start execution of the whole chain. RxObservable does nothing until subscriber arrives.