Retrofit和RxJava:如何结合两个请求并获得两个结果?
我需要提出两个服务请求,并将结果结合起来:
ServiceA()=> [{"id":1,"name":"title"},{"id":1,"name":"title"}]
ServiceB( id
)=> {"field":"value","field1":"value"}
目前,我设法结合了结果,但是我需要将id
作为parameter passing给ServiceB并获得第一个结果。
我到目前为止所尝试的是:
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(...);
编辑
解决scheme根据@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(....); }
据我所知 – 你需要根据另一个请求的结果提出请求,并结合这两个结果。 为此,您可以使用以下flatMap
运算符变体: Observable.flatMap(Func1 collectionSelector,Func2 resultSelector)
返回一个Observable,它将指定函数的结果发送到由源Observable和指定集合Observable发出的一对值。
简单的例子来指出如何重写你的代码:
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 }
使用lambdas:
private void doTheJob() { makeRequestToServiceA() .flatMap(responseFromServiceA -> makeRequestToServiceB(responseFromServiceA), (responseFromServiceA, responseFromServiceB) -> Observable.just("here is combined result!")) //... }
你正在寻找的操作符是flatMap()
serviceA.getAllGeneros("movie","list","da0d692f7f62a1dc687580f79dc1e6a0") .flatMap(genres -> serviceB.getAllMovies(genres.getId() ......))