/**
   * Pre caches the given set of image urls. We recommend using this method to warm the image cache
   * before calling {@link CustomEventNativeListener#onNativeAdLoaded}. Doing so will force images
   * to cache before displaying the ad.
   */
  static void preCacheImages(
      @NonNull final Context context,
      @NonNull final List<String> imageUrls,
      @NonNull final ImageListener imageListener) {
    final ImageLoader imageLoader = Networking.getImageLoader(context);
    // These Atomics are only accessed on the main thread.
    // We use Atomics here so we can change their values while keeping a reference for the inner
    // class.
    final AtomicInteger imageCounter = new AtomicInteger(imageUrls.size());
    final AtomicBoolean anyFailures = new AtomicBoolean(false);
    ImageLoader.ImageListener volleyImageListener =
        new ImageLoader.ImageListener() {
          @Override
          public void onResponse(
              final ImageLoader.ImageContainer imageContainer, final boolean isImmediate) {
            // Image Loader returns a "default" response immediately. We want to ignore this
            // unless the image is already cached.
            if (imageContainer.getBitmap() != null) {
              final int count = imageCounter.decrementAndGet();
              if (count == 0 && !anyFailures.get()) {
                imageListener.onImagesCached();
              }
            }
          }

          @Override
          public void onErrorResponse(final VolleyError volleyError) {
            MoPubLog.d("Failed to download a native ads image:", volleyError);
            boolean anyPreviousErrors = anyFailures.getAndSet(true);
            imageCounter.decrementAndGet();
            if (!anyPreviousErrors) {
              imageListener.onImagesFailedToCache(NativeErrorCode.IMAGE_DOWNLOAD_FAILURE);
            }
          }
        };

    for (String url : imageUrls) {
      if (TextUtils.isEmpty(url)) {
        anyFailures.set(true);
        imageListener.onImagesFailedToCache(NativeErrorCode.IMAGE_DOWNLOAD_FAILURE);
        return;
      }
      imageLoader.get(url, volleyImageListener);
    }
  }