java Retrofit 和 RxJava:如何组合两个请求并访问两个结果?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/41786439/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Retrofit and RxJava: How to combine two requests and get access to both results?
提问by David Hackro
I need to make two requests for services and combine it results:
我需要对服务提出两个请求并将其结果组合起来:
ServiceA() => [{"id":1,"name":"title"},{"id":1,"name":"title"}]
服务A() => [{"id":1,"name":"title"},{"id":1,"name":"title"}]
ServiceB(id
) => {"field":"value","field1":"value"}
服务B( id
) => {"field":"value","field1":"value"}
Currently, I have managed to combine the results, but I need to pass id
as a parameter to the ServiceBand get access to the first result.
目前,我已设法组合结果,但我需要将其id
作为参数传递给ServiceB并访问第一个结果。
What I tried so far:
到目前为止我尝试过的:
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(...);
Edit
编辑
Solutionaccording to @Maxim Ostrovidov's answer:
根据@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(....);
}
回答by Maksim Ostrovidov
As I understand - you need to make a request based on result of another request and combine both results. For that purpose you can use this flatMap
operator variant: Observable.flatMap(Func1 collectionSelector, Func2 resultSelector)
据我了解 - 您需要根据另一个请求的结果发出请求并将两个结果结合起来。为此,您可以使用此flatMap
运算符变体:Observable.flatMap(Func1 collectionSelector, Func2 resultSelector)
Returns an Observable that emits the results of a specified function to the pair of values emitted by the source Observable and a specified collection Observable.
返回一个 Observable,该 Observable 将指定函数的结果发送到源 Observable 和指定集合 Observable 发出的值对。
Simple example to point you how to rewrite your code:
指导您如何重写代码的简单示例:
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
}
Using lambdas:
使用 lambda:
private void doTheJob() {
makeRequestToServiceA()
.flatMap(responseFromServiceA -> makeRequestToServiceB(responseFromServiceA),
(responseFromServiceA, responseFromServiceB) -> Observable.just("here is combined result!"))
//...
}
回答by LordRaydenMK
The operator you are looking for is flatMap()
您要找的运营商是 flatMap()
serviceA.getAllGeneros("movie","list","da0d692f7f62a1dc687580f79dc1e6a0")
.flatMap(genres -> serviceB.getAllMovies(genres.getId() ......))