Правильно ли я использую flatMap для объединения результатов нескольких вызовов API?
Я хочу сделать несколько вызовов API (с тремя различными запросами) и объединить результаты, а затем отобразить их в onNext()
, Это работает, но я обеспокоен тем, что flatMap не идеально подходит для этого.
@GET("www.examle.com/api/data/")
Observable<WebResultsResponse> getWebResults(@Query("param1") String query);
-----
private List<WebResult> resultsList;
private void requestWebResults(String query) {
resultsList.clear();
final Observable<List<WebResult>> observable = MainApplication.apiProvider.getApiProviderA.getWebResults("query1")
.subscribeOn(Schedulers.io())
.flatMap(new Function<WebResultsResponse, ObservableSource<List<WebResult>>>() {
@Override
public ObservableSource<List<WebResult>> apply(WebResultsResponse response) throws Exception {
if(response.getData() != null && response.getData().getResults() != null)
resultsList.addAll(response.getData().getResults());
return MainApplication.apiProvider.getApiProviderA.getWebResults("query2")
.flatMap(new Function<WebResultsResponse, ObservableSource<List<WebResult>>>() {
@Override
public ObservableSource<List<WebResult>> apply(WebResultsResponse response) throws Exception {
if(response.getData() != null && response.getData().getResults() != null)
resultsList.addAll(response.getData().getResults());
return MainApplication.apiProvider.getApiProviderA.getWebResults("query3")
.flatMap(new Function<WebResultsResponse, ObservableSource<List<WebResult>>>() {
@Override
public ObservableSource<List<WebResult>> apply(WebResultsResponse response) throws Exception {
if(response.getData() != null && response.getData().getResults() != null)
resultsList.addAll(response.getData().getResults());
return Observable.just(resultsList);
}
});
}
});
}
})
.observeOn(AndroidSchedulers.mainThread());
observer = new DisposableObserver<List<WebResult>>() {
@Override
public void onNext(List<WebResult> results) {
// do something with results
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
};
observable.subscribe(observer);
}
Это правильное использование flatMap()
? Могу ли я как-нибудь передать resultsList
вниз по цепочке вместо того, чтобы объявить его в качестве глобальной переменной?
2 ответа
Вы можете просто объединить их, если вам все равно, кто из них вернется первым
Observable<List<WebResult>> observable = MainApplication.apiProvider.getApiProviderA.getWebResults("query1")
.mergeWith(MainApplication.apiProvider.getApiProviderA.getWebResults("query2"))
.mergeWith(MainApplication.apiProvider.getApiProviderA.getWebResults("query3"))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
в onNext() вы получите каждый результат в виде отдельного списка, если вы хотите получить результат, когда все они сделаны со всеми результатами, которые вы можете использовать
Observable<List<WebResult>> observable = Observable.zip(MainApplication.apiProvider.getApiProviderA.getWebResults("query1"), MainApplication.apiProvider.getApiProviderA.getWebResults("query2"), MainApplication.apiProvider.getApiProviderA.getWebResults("query3"), (webResults, webResults2, webResults3) -> {
List<WebResult> allResults = new ArrayList<>();
allResults.addAll(webResults);
allResults.addAll(webResults2);
allResults.addAll(webResults3);
return allResults;
});
И в onNext() вы получите одну эмиссию со всеми результатами, сложенными вместе
С помощью ответа elmorabea я придумал это решение, используя zip
:
List<Observable<WebResultsResponse>> results = new ArrayList<>();
results.add(MainApplication.apiProvider.getApiProviderA.getWebResults("query1"));
results.add(MainApplication.apiProvider.getApiProviderA.getWebResults("query2"));
results.add(MainApplication.apiProvider.getApiProviderA.getWebResults("query3"));
Observable<List<WebResult>> observable = Observable.zip(results, new Function<Object[], List<WebResult>>() {
@Override
public List<WebResult> apply(Object[] responses) throws Exception {
List<WebResult> allResults = new ArrayList<>();
for(int i=0; i<responses.length; i++) {
WebResultsResponse response = (WebResultsResponse)responses[i];
if(response != null && response.getData() != null && response.getData().getResults() != null)
allResults.addAll(response.getData().getResults());
}
return allResults;
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io());