如何在Android上使用Retrofit2和rxjava2发出多个请求?

时间:2019-01-27 19:41:26

标签: android rx-java retrofit2 rx-java2

在我的Android应用程序中,我想使用改造和rxjava来获取多个HTTP请求以获取json数据。请求的数量取决于用户的首选项(1到40)。每个请求都是独立的,并返回相同的类型。因此,我尝试应用此问题(How to make multiple request and wait until data is come from all the requests in retrofit 2.0 - android)中推荐的方法,该问题使用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类以获取数据

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();

    }
}

它不会给出错误,但也不会给出响应,因为我无法处理响应。有人可以帮我组合每个请求的结果吗?我已经搜索了所有问题,但找不到这样的示例。

3 个答案:

答案 0 :(得分:1)

尝试使用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);
            }
        });

已编辑更新了方法

答案 1 :(得分:0)

lat = rand(-90.0..90.0) lon = rand(-180.0..180.0) 是请求返回的项目数组。假设您的每个请求都返回一个Object[] objects,并且您想将所有List<NewsItem>合并为一个NewsItem,那么我认为您可以执行以下操作:

List<NewsItem>

请注意类型转换。

答案 2 :(得分:0)

如果您获取的数据类型是相同的 列表 ,并且请求是多个,则可以使用递归方法进行1到n 请求,并在每次成功时添加数据 List