[英]How to make multiple requests using retrofit2 and rxjava2 on android?
In my android app, I want to make multiple http requests using retrofit and rxjava to fetch json data.在我的 android 应用程序中,我想使用改造和 rxjava 发出多个 http 请求来获取 json 数据。 The number of request depends on the user's preferences (1 up to 40).
请求的数量取决于用户的偏好(1 到 40)。 Each request is independent and returns same type.
每个请求都是独立的并返回相同的类型。 So, i tried to apply the way that is recommended in this question ( How to make multiple request and wait until data is come from all the requests in retrofit 2.0 - android ) which uses the zip function of rx-java.
因此,我尝试应用此问题中推荐的方式( 如何发出多个请求并等待数据来自改造 2.0 - android 中的所有请求),该方式使用 rx-java 的 zip 功能。 But i couldn't find a way to get and combine the results of each request.
但是我找不到一种方法来获取和组合每个请求的结果。 Response type that i used for single request in retrofit was
Response<List<NewsItem>>
where NewsItem is my custom object.我在改造中用于单个请求的响应类型是
Response<List<NewsItem>>
其中 NewsItem 是我的自定义对象。 (the response is json array actually but in a single request retrofit automatically handles it and converts it into list of my custom object) What i tried so far is below: (响应实际上是 json 数组,但在单个请求改造中会自动处理它并将其转换为我的自定义对象列表)到目前为止我尝试过的内容如下:
public interface API {
String BASE_URL = "xxx/";
@GET("news/{source}")
Observable<List<NewsItem>> getNews(@Path("source") String source);
}
public class NewsVM extends AndroidViewModel {
public NewsVM(Application application){
super(application);
}
private MutableLiveData<List<NewsItem>> newsLiveData;
public LiveData<List<NewsItem>> getNewsLiveData(ArrayList<String> mySourceList) {
newsLiveData = new MutableLiveData<>();
loadNews(mySourceList);
return newsLiveData;
}
private void loadNews(ArrayList<String> mySourceList) {
Gson gson = new GsonBuilder().setLenient().create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API.BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
API api = retrofit.create(API.class);
//Gathering the requests into list of observables
List<Observable<?>> requests = new ArrayList<>();
for(String source: mySourceList){
requests.add(api.getNews(source));
}
// Zip all requests
Observable.zip(requests, new Function<Object[], List<NewsItem>>() {
@Override
public List<NewsItem> apply(Object[] objects) throws Exception {
// I am not sure about the parameters and return type in here, probably wrong
return new ArrayList<>();
}
})
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.newThread())
.subscribe(
new Consumer<List<NewsItem>>() {
@Override
public void accept(List<NewsItem> newsList) throws Exception {
Log.d("ONRESPONSE",newsList.toString());
newsLiveData.setValue(newsList);
}
},
new Consumer<Throwable>() {
@Override
public void accept(Throwable e) throws Exception {
Log.d("ONFAILURE", e.getMessage());
}
}
).dispose();
}
}
It doesn't give error but doesn't give response also since I couldn't handle the response.它没有给出错误,但也没有给出响应,因为我无法处理响应。 Can anybody help me in combining the results of the each request?
有人可以帮我合并每个请求的结果吗? I've searched all the questions but can't find an example like this.
我已经搜索了所有问题,但找不到这样的例子。
try to use Observable.from(Iterable<? extends T> iterable)
( Observable.fromArray()
in rx-java2) instead of zip
So you'll have something like:尝试使用
Observable.from(Iterable<? extends T> iterable)
( rx-java2 中的Observable.fromArray()
)而不是zip
所以你会有类似的东西:
Observable.from(mySourceList)
.flatMap(new Func1<String, Observable<List<NewsItem>>>() {
@Override
public Observable<List<NewsItem>> call(String source) {
return api.getNews(source);
}
})
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.newThread())
.toList() // This will give you List<List<NewsItem>>
.map(new Func1<List<List<NewsItem>>, List<NewsItem>>() {
@Override
public List<NewsItem> call(List<List<NewsItem>> listOfList) {
//Merged list of lists to single list using Guava Library
List<NewsItem> list = Lists.newArrayList(Iterables.concat(listOfList));
return list;
}
})
.subscribe(new Subscriber<List<NewsItem>>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
}
@Override
public void onNext(List<NewsItem> newsList) {
//Attached the final newslist to livedata
newsLiveData.setValue(newsList);
}
});
EDITED Updated the method已编辑更新了方法
Object[] objects
is the array of items returned by the requests. Object[] objects
是请求返回的项目数组。 Assuming that each of your request returns a List<NewsItem>
and you wanted to combine all NewsItem
into a single List<NewsItem>
, I think you can do something along the lines of:假设您的每个请求都返回一个
List<NewsItem>
并且您想将所有NewsItem
合并到一个List<NewsItem>
,我认为您可以执行以下操作:
private void loadNews(ArrayList<String> mySourceList) {
...
// Zip all requests
Observable.zip(requests, new Function<Object[], List<NewsItem>>() {
@Override
public List<NewsItem> apply(Object[] objects) throws Exception {
List<NewsItem> combinedNewsItems = new ArrayList<>();
for (Object response : objects) {
combinedNewsItems.addAll((List<NewsItem>) response);
}
return combinedNewsItems;
}
})
.subscribeOn(Schedulers.io())
...
}
Be aware of the type casting.注意类型转换。
如果您获取的数据类型是相同的List并且请求是多个,那么您可以使用递归方法进行 1 到 n 个请求,并在每次成功时添加数据List 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.