nostra13/Android-Universal-Image-Loader · error · IllegalArgumentException

ImageAware should wrap ImageView. ImageViewAware is expected

Error message

ImageAware should wrap ImageView. ImageViewAware is expected.

What it means

RoundedVignetteBitmapDisplayer extends RoundedBitmapDisplayer and repeats the same guard: display() only accepts ImageViewAware targets, throwing IllegalArgumentException otherwise. The vignette drawable it creates must be set on an ImageView via setImageDrawable, so non-ImageView awares are rejected. The failure happens at display time, after download and decode succeeded.

Source

Thrown at library/src/main/java/com/nostra13/universalimageloader/core/display/RoundedVignetteBitmapDisplayer.java:47

 * Romain Guy's article</a>. It rounds images using custom drawable drawing. Original bitmap isn't changed.
 * <br />
 * <br />
 * If this implementation doesn't meet your needs then consider
 * <a href="https://github.com/vinc3m1/RoundedImageView">this project</a> for usage.
 *
 * @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
 * @since 1.9.1
 */
public class RoundedVignetteBitmapDisplayer extends RoundedBitmapDisplayer {

	public RoundedVignetteBitmapDisplayer(int cornerRadiusPixels, int marginPixels) {
		super(cornerRadiusPixels, marginPixels);
	}

	@Override
	public void display(Bitmap bitmap, ImageAware imageAware, LoadedFrom loadedFrom) {
		if (!(imageAware instanceof ImageViewAware)) {
			throw new IllegalArgumentException("ImageAware should wrap ImageView. ImageViewAware is expected.");
		}

		imageAware.setImageDrawable(new RoundedVignetteDrawable(bitmap, cornerRadius, margin));
	}

	protected static class RoundedVignetteDrawable extends RoundedDrawable {

		RoundedVignetteDrawable(Bitmap bitmap, int cornerRadius, int margin) {
			super(bitmap, cornerRadius, margin);
		}

		@Override
		protected void onBoundsChange(Rect bounds) {
			super.onBoundsChange(bounds);
			RadialGradient vignette = new RadialGradient(
					mRect.centerX(), mRect.centerY() * 1.0f / 0.7f, mRect.centerX() * 1.3f,
					new int[]{0, 0, 0x7f000000}, new float[]{0.0f, 0.7f, 1.0f},
					Shader.TileMode.CLAMP);

View on GitHub (pinned to ba33ec64d0)

Solutions

  1. Supply an ImageViewAware target (or the ImageView itself) when the vignette displayer is active
  2. Split options: keep a displayer-free variant for NonViewAware/prefetch loads
  3. Substitute a custom BitmapDisplayer without the instanceof check for non-view pipelines

Example fix

// before
imageLoader.displayImage(uri, nonViewAware, baseOptions); // baseOptions has RoundedVignetteBitmapDisplayer

// after
DisplayImageOptions plain = baseOptions.newBuilder().displayer(null).build();
imageLoader.displayImage(uri, nonViewAware, plain);
Defensive patterns

Strategy: type-guard

Validate before calling

if (aware instanceof ImageViewAware) {
    imageLoader.displayImage(uri, aware, vignetteOptions);
} else {
    imageLoader.displayImage(uri, aware, vignetteOptions.newBuilder().displayer(null).build());
}

Type guard

private static boolean isVignetteSafe(ImageAware aware, DisplayImageOptions opts) {
    return !(opts.getDisplayer() instanceof RoundedVignetteBitmapDisplayer)
            || aware instanceof ImageViewAware;
}

Prevention

When it happens

Trigger: Configuring options with .displayer(new RoundedVignetteBitmapDisplayer(radius, margin)) and invoking displayImage with NonViewAware or any custom ImageAware that does not extend ImageViewAware. Inheriting display options from a base class that includes the vignette displayer and reusing them for non-view loads.

Common situations: Central DisplayImageOptions constants shared across an app (image grid + background prefetch) where one path uses NonViewAware; refactoring from ImageView-only loading to generic ImageAware targets without stripping the displayer.

Related errors


AI-assisted analysis of nostra13/Android-Universal-Image-Loader@ba33ec64d0 (2026-08-14). Data as JSON: /api/errors/1b13cb26455e9b6c. Report an issue: GitHub.