首页 > 解决方案 > 如何在继续循环之前等待回调完成?

问题描述

我正在尝试在 for 循环中添加restMediarestaurantMediaListin中。onResponse但是,当循环结束时,restaurantMediaList为空。onResponse我怎样才能解决这个问题,让它在进行下一次迭代之前先等待完成?

public void getImages(List<Restaurant> restaurantList, OnImageReceivedCallback callback){
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://example.com")
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        WordpressAPICall wordpressAPICall = retrofit.create(WordpressAPICall.class);
        
        for(int i = 0; i < restaurantList.size(); i++){
            String featuredMediaURL = restaurantList.get(i).get_links().getFeaturedMedia().get(0).getHref();
            featuredMediaURL.substring(featuredMediaURL.indexOf("v2")+1);
            Call<RestaurantMedia> restMediaCall = wordpressAPICall.getImage(featuredMediaURL);

            restMediaCall.enqueue(new Callback<RestaurantMedia>() {
                @Override
                public void onResponse(Call<RestaurantMedia> call, Response<RestaurantMedia> response) {
                    RestaurantMedia restMedia = response.body();
                    restaurantMediaList.add(restMedia);
                    //callback.onRestaurantListReceived(restaurantModels, restMedia);
                }

                @Override
                public void onFailure(Call<RestaurantMedia> call, Throwable t) {
                    Log.d("Fail to get media", t.toString());
                }
            });
        }
        
        callback.onImageReceived(restaurantMediaList);
        
    }

标签: javaandroidretrofit2

解决方案


请记住,有restaurantList.size()不同的线程(每个都会触发一个网络请求),您唯一的选择是使用一些锁。

如果有一个 API 可以同时获取所有图像,请使用它并使用我的第一个代码来等待结果。

我还建议使用超时,因为如果由于某种原因onResponseANDonFailure不会被调用,您的调用线程将永远休眠。根据需要调整超时。

等待每个线程分别完成非常耗时,所以我建议让它们异步并在所有线程完成后继续。

我将向您展示这两种选择。

等待每一个单独等待:

CountDownLatch countDownLatch = new CountDownLatch(1);
restMediaCall.enqueue(new Callback<RestaurantMedia>() {
    @Override
    public void onResponse(Call<RestaurantMedia> call, Response<RestaurantMedia> response) {
          // Do your thing
          countDownLatch.countDown();
     }

    @Override
    public void onFailure(Call<RestaurantMedia> call, Throwable t) {
          // Do your thing
        countDownLatch.countDown();
    }
});
countDownLatch.await(1L, TimeUnit.SECONDS); // join thread with timeout of second

一起等待所有线程:

public void getImages(List<Restaurant> restaurantList, OnImageReceivedCallback callback){
    // Do your thing
    CountDownLatch countDownLatch = new CountDownLatch(restaurantList.size());
    for(int i = 0; i < restaurantList.size(); i++){
        // Do your thing
        restMediaCall.enqueue(new Callback<RestaurantMedia>() {
            @Override
            public void onResponse(Call<RestaurantMedia> call, Response<RestaurantMedia> response) {
              // Do your thing
              countDownLatch.countDown();
             }

            @Override
            public void onFailure(Call<RestaurantMedia> call, Throwable t) {
                 // Do your thing
                 countDownLatch.countDown();
            }
        });
    }
    countDownLatch.await(1L *  restaurantList.size(), TimeUnit.SECONDS); // join thread with timeout of second for each item
}

推荐阅读