如何进行多个请求并等待数据来自retrofit 2.0中的所有请求 - android

Dev*_*wal 45 android retrofit2

当前代码:

Retrofit retrofit = new Retrofit.Builder()
                  .baseUrl(Constant.BASEURL)
                  .addConverterFactory(GsonConverterFactory.create())
                  .build();

APIService service = retrofit.create(APIService.class);

Call<ResponseWrap> call = service.getNewsData();

call.enqueue(new Callback<ResponseWrap>() {

  @Override
  public void onResponse(Call<ResponseWrap> call1, Response<ResponseWrap> response) {
    if (response.isSuccess()) {

        ResponseWrap finalRes = response.body();
        for(int i=0; i<finalRes.getResponse().getResults().size(); ++i){
            String title = finalRes.getResponse().getResults().get(i).getWebTitle();
            News n = new News(titleCategory, title, null);
            newsList.add(n);
        }

        AdapterRecommendation adapter = new AdapterRecommendation(getApplicationContext(), newsList);
        listView.setAdapter(adapter);

    }
    else{
        Toast.makeText(getApplicationContext(), "onResponse  - something wrong" + response.message(), Toast.LENGTH_LONG).show();
    }
  }

  @Override
  public void onFailure(Call<ResponseWrap> call1, Throwable t) {
      Toast.makeText(getApplicationContext(), "exception: " + t.getMessage(), Toast.LENGTH_LONG).show();
  }
});
Run Code Online (Sandbox Code Playgroud)

工作良好.

现在我想进行多次呼叫(呼叫次数将在运行时决定),所有呼叫都以相同的格式提供数据.所有调用的数据都需要添加到newsList中.一旦所有呼叫都有数据并添加到newsList,请致电

AdapterRecommendation adapter = new AdapterRecommendation(getApplicationContext(), newsList);
listView.setAdapter(adapter);
Run Code Online (Sandbox Code Playgroud)

任何人都可以帮助我从多个调用中获取数据的最佳方法是什么,并等待所有请求在改进2.0中没有结束.

Кла*_*арц 45

等待所有请求完成的干净利落的方法是将Retrofit2与RxJava2及其zip功能结合使用.

什么zip基本上构造了新的observable,等待所有的改装Observable请求完成,然后它将发出自己的结果.

以下是Observables的Retrofit2接口示例:

public interface MyBackendAPI {
  @GET("users/{user}")
  Observable<User> getUser(@Path("user") String user);

  @GET("users/{user}/photos")
  Observable<List<Photo>> listPhotos(@Path("user") String user);

  @GET("users/{user}/friends")
  Observable<List<User>> listFriends(@Path("user") String user);
}
Run Code Online (Sandbox Code Playgroud)

在您要发出多个请求的代码中,只有在所有请求完成后才能执行其他操作,然后您可以编写以下内容:

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https://api.example.com/")
            .build();

    MyBackendAPI backendApi = retrofit.create(MyBackendAPI.class);

    List<Observable<?>> requests = new ArrayList<>();

    // Make a collection of all requests you need to call at once, there can be any number of requests, not only 3. You can have 2 or 5, or 100.
    requests.add(backendApi.getUser("someUserId"));
    requests.add(backendApi.listPhotos("someUserId"));
    requests.add(backendApi.listFriends("someUserId"));

    // Zip all requests with the Function, which will receive the results.
    Observable.zip(
            requests,
            new Function<Object[], Object>() {
                @Override
                public Object apply(Object[] objects) throws Exception {
                    // Objects[] is an array of combined results of completed requests

                    // do something with those results and emit new event
                    return new Object();
                }
            })
            // After all requests had been performed the next observer will receive the Object, returned from Function
            .subscribe(
                    // Will be triggered if all requests will end successfully (4xx and 5xx also are successful requests too)
                    new Consumer<Object>() {
                        @Override
                        public void accept(Object o) throws Exception {
                            //Do something on successful completion of all requests
                        }
                    },

                    // Will be triggered if any error during requests will happen
                    new Consumer<Throwable>() {
                        @Override
                        public void accept(Throwable e) throws Exception {
                            //Do something on error completion of requests
                        }
                    }
            );
Run Code Online (Sandbox Code Playgroud)

就这样 :)


以防万一,想要显示相同的代码是什么样的Kotlin.

    val retrofit = Retrofit.Builder()
            .baseUrl("https://api.example.com/")
            .build()

    val backendApi = retrofit.create(MyBackendAPI::class.java)

    val requests = ArrayList<Observable<*>>()

    requests.add(backendApi.getUser())
    requests.add(backendApi.listPhotos())
    requests.add(backendApi.listFriends())

    Observable
            .zip(requests) {
                // do something with those results and emit new event
                Any() // <-- Here we emit just new empty Object(), but you can emit anything
            }
            // Will be triggered if all requests will end successfully (4xx and 5xx also are successful requests too)
            .subscribe({
                //Do something on successful completion of all requests
            }) {
                //Do something on error completion of requests
            }
Run Code Online (Sandbox Code Playgroud)

  • android.os.NetworkOnMainThreadException发生了,你对此有所了解吗? (3认同)
  • 我做到了,我为 .zip 启用了两种行为,.subscribeOn(Schedulers.io()) .observeOn(Schedulers.newThread()),在它消失后,您的回答为我节省了更多时间。 (2认同)
  • @SandunPriyanka我忘了我的回答与改造有关。所以是的,observeOn / subscribeOn应该可以解决问题。这里还有另一个答案:/sf/answers/3080532801/ (2认同)