android - 如何发出多个请求并等待数据来自改造 2.0 中的所有请求 - android

标签 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();
  }
});

工作正常。

现在我想进行多次调用(调用次数将在运行时确定)并且所有调用都以相同格式提供数据。所有调用的数据都需要添加到 newsList。一旦所有调用的数据都可用并添加到 newsList,调用

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

谁能帮助我从多个调用中获取数据的最佳方法是什么,然后等到改造 2.0 中的所有请求都没有结束。

最佳答案

等到所有请求都完成的干净整洁的方法是将Retrofit2与RxJava2及其zip函数结合使用。

zip 所做的基本上是构造新的 observable,它会等到您的所有改造 Observable 请求都完成,然后它会发出自己的结果。

这是一个带有 Observables 的 Retrofit2 接口(interface)示例:

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

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

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

就是这样:)


以防万一想展示相同的代码在 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
            }

关于android - 如何发出多个请求并等待数据来自改造 2.0 中的所有请求 - android,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36474120/

相关文章:

java - 响应代码 422 转到 onFailure 方法

android - Retrofit2 如何将/放在动态 baseUrl 的末尾?

java - 在应用程序启动时播放电影

java - (Android)如何捕获应用程序主线程终止(如果将其置于后台)

android - 如何在 Android 设备中获取网络适配器的名称

java - 让 GsonConverterFactory 解析某些字段?

android - ViewPager 拒绝展示它漂亮的小脑袋

Adobe Air StageWebView 中的 Android 远程 Chrome 调试

android - 尝试使用 Retrofit 发出 get 请求时无法为类 java.lang.Object 创建调用适配器

java - Android - 无法使用 Retrofit2 获取 JSON