如何在 android 上使用 retrofit2 和 rxjava2 发出多个请求?
How to make multiple requests using retrofit2 and rxjava2 on android?
在我的 android 应用中,我想使用改造和 rxjava 发出多个 http 请求来获取 json 数据。请求的数量取决于用户的偏好(1 到 40)。每个请求都是独立的并且 returns 类型相同。因此,我尝试应用此问题 () 中推荐的方法,该方法使用 rx-java 的 zip 函数。但是我找不到一种方法来获取和合并每个请求的结果。我在改造中用于单个请求的响应类型是 Response<List<NewsItem>>
,其中 NewsItem 是我的自定义对象。 (响应实际上是 json 数组,但在单个请求改造中会自动处理它并将其转换为我的自定义对象列表)到目前为止我尝试过的如下:
我的API界面
public interface API {
String BASE_URL = "xxx/";
@GET("news/{source}")
Observable<List<NewsItem>> getNews(@Path("source") String source);
}
Viewmodel class 获取数据
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();
}
}
它没有给出错误,但也没有给出响应,因为我无法处理响应。有人可以帮我合并每个请求的结果吗?我搜索了所有问题,但找不到这样的示例。
Object[] objects
是请求返回的项目数组。假设你的每个请求 returns 一个 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())
...
}
注意类型转换。
如果您获得的数据类型与List和请求相同是多个那么你可以使用递归方法进行 1 到 n 请求并在每个上添加数据 List成功。
尝试使用 Observable.from(Iterable<? extends T> iterable)
(Observable.fromArray()
in rx-java2)而不是 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);
}
});
已编辑 更新了方法
在我的 android 应用中,我想使用改造和 rxjava 发出多个 http 请求来获取 json 数据。请求的数量取决于用户的偏好(1 到 40)。每个请求都是独立的并且 returns 类型相同。因此,我尝试应用此问题 (Response<List<NewsItem>>
,其中 NewsItem 是我的自定义对象。 (响应实际上是 json 数组,但在单个请求改造中会自动处理它并将其转换为我的自定义对象列表)到目前为止我尝试过的如下:
我的API界面
public interface API {
String BASE_URL = "xxx/";
@GET("news/{source}")
Observable<List<NewsItem>> getNews(@Path("source") String source);
}
Viewmodel class 获取数据
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();
}
}
它没有给出错误,但也没有给出响应,因为我无法处理响应。有人可以帮我合并每个请求的结果吗?我搜索了所有问题,但找不到这样的示例。
Object[] objects
是请求返回的项目数组。假设你的每个请求 returns 一个 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())
...
}
注意类型转换。
如果您获得的数据类型与List和请求相同是多个那么你可以使用递归方法进行 1 到 n 请求并在每个上添加数据 List成功。
尝试使用 Observable.from(Iterable<? extends T> iterable)
(Observable.fromArray()
in rx-java2)而不是 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);
}
});
已编辑 更新了方法