简体   繁体   中英

How to wait for callback to finish before continuing the loop?

I'm trying to add restMedia to restaurantMediaList in onResponse within a for loop. However, when the loop is finished, restaurantMediaList is null. How can I fix this in such a way that it waits for onResponse to be finished first before proceeding with the next iteration?

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

Keep in mind that there are restaurantList.size() different threads (each fires a network request) and the only choice you have is to use some lock.

If there is an API that fetches all of the images together please use it and use my 1st code to wait for result.

I also recommend using timeout because if, for some reason, onResponse AND onFailure will not be called, your calling thread will sleep forever. Tweak the timeout as you see fit.

Waiting for each thread to finish separately is extremely time consuming so I'd recommend to let them go asynchronous and continue when all of them are done.

I'll show you both options.

Wait for each one to wait separately:

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

Waiting for all threads together:

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
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM