squareup rxjava2 rxjava ejemplo java android rx-java retrofit2

rxjava2 - Retrofit y RxJava: ¿Cómo combinar dos solicitudes y obtener acceso a ambos resultados?



retrofit2 android (2)

El operador que está buscando es flatMap()

serviceA.getAllGeneros("movie","list","da0d692f7f62a1dc687580f79dc1e6a0") .flatMap(genres -> serviceB.getAllMovies(genres.getId() ......))

Necesito hacer dos solicitudes de servicios y combinar los resultados:

ServiceA () => [{"id":1,"name":"title"},{"id":1,"name":"title"}]

ServiceB ( id ) => {"field":"value","field1":"value"}

Actualmente, he logrado combinar los resultados, pero necesito pasar la id como parámetro al ServiceB y obtener acceso al primer resultado.

Lo que probé hasta ahora:

Retrofit repo = new Retrofit.Builder() .baseUrl("https://api.themoviedb.org/3/genre/") .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build(); Observable<GenerosResponse> Genres = repo .create(services.class) .getAllGeneros("movie","list","da0d692f7f62a1dc687580f79dc1e6a0") .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()); Observable<ResponseMovies> Movies = repo .create(services.class) .getAllMovies("28","movies","da0d692f7f62a1dc687580f79dc1e6a0",12) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()); Observable<CollectionsMovies> combined = Observable.zip(Genres, Movies, new Func2<GenerosResponse, ResponseMovies, CollectionsMovies>() { @Override public CollectionsMovies call(GenerosResponse generosResponse, ResponseMovies responseMovies) { return new CollectionsMovies(generosResponse, responseMovies); } }); combined. subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(...);

Editar

Solución según la respuesta de @Maxim Ostrovidov:

private Observable<GenerosResponse> makeRequestToServiceA() { return service.getAllGeneros("movie","list","da0d692f7f62a1dc687580f79dc1e6a0"); //some network call } private Observable<ResponseMovies> makeRequestToServiceB(Genre genre) { return service.getAllMovies(genre.getId(),"movies","da0d692f7f62a1dc687580f79dc1e6a0","created_at.asc"); //some network call based on response from ServiceA } void doTheJob() { makeRequestToServiceA() .flatMap(userResponse -> Observable.just(userResponse.getGenres())) //get list from response .flatMapIterable(baseDatas -> baseDatas) .flatMap(new Func1<Genre, Observable<? extends ResponseMovies>>() { @Override public Observable<? extends ResponseMovies> call(Genre genre) { return makeRequestToServiceB(genre); } }, new Func2<Genre, ResponseMovies, CollectionsMovies>() { @Override public CollectionsMovies call(Genre genre, ResponseMovies responseMovies) { return new CollectionsMovies(genre,responseMovies); } }). subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(....); }


Según tengo entendido, debe realizar una solicitud basada en el resultado de otra solicitud y combinar ambos resultados. Para ello, puede utilizar esta variante de operador flatMap : Observable.flatMap (Func1 collectionSelector, Func2 resultSelector)

Devuelve un Observable que emite los resultados de una función específica al par de valores emitidos por el Observable de origen y una colección específica Observable.

Ejemplo simple para indicarle cómo reescribir su código:

private Observable<String> makeRequestToServiceA() { return Observable.just("serviceA response"); //some network call } private Observable<String> makeRequestToServiceB(String serviceAResponse) { return Observable.just("serviceB response"); //some network call based on response from ServiceA } private void doTheJob() { makeRequestToServiceA() .flatMap(new Func1<String, Observable<? extends String>>() { @Override public Observable<? extends String> call(String responseFromServiceA) { //make second request based on response from ServiceA return makeRequestToServiceB(responseFromServiceA); } }, new Func2<String, String, Observable<String>>() { @Override public Observable<String> call(String responseFromServiceA, String responseFromServiceB) { //combine results return Observable.just("here is combined result!"); } }) //apply schedulers, subscribe etc }

Usando lambdas:

private void doTheJob() { makeRequestToServiceA() .flatMap(responseFromServiceA -> makeRequestToServiceB(responseFromServiceA), (responseFromServiceA, responseFromServiceB) -> Observable.just("here is combined result!")) //... }