簡體   English   中英

如何在android上使用retrofit2和rxjava2發出多個請求?

[英]How to make multiple requests using retrofit2 and rxjava2 on android?

在我的 android 應用程序中,我想使用改造和 rxjava 發出多個 http 請求來獲取 json 數據。 請求的數量取決於用戶的偏好(1 到 40)。 每個請求都是獨立的並返回相同的類型。 因此,我嘗試應用此問題中推薦的方式( 如何發出多個請求並等待數據來自改造 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);
}

獲取數據的視圖模型類

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

    }
}

它沒有給出錯誤,但也沒有給出響應,因為我無法處理響應。 有人可以幫我合並每個請求的結果嗎? 我已經搜索了所有問題,但找不到這樣的例子。

嘗試使用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);
            }
        });

已編輯更新了方法

Object[] objects是請求返回的項目數組。 假設您的每個請求都返回一個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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM