A fast and efficient open source media management and image loading framework for Android that wraps media decoding, memory and disk caching, and resource pooling into a simple and easy to use interface.
—
This document provides comprehensive coverage of Glide's target system and loading methods, covering the complete API surface for handling image loading destinations and request execution.
The base Target interface defines the contract for all image loading destinations in Glide.
public interface Target<R> {
/**
* Called when the load has started
* @param placeholder The placeholder drawable to show during loading
*/
void onLoadStarted(@Nullable Drawable placeholder);
/**
* Called when the load has failed
* @param errorDrawable The error drawable to show on failure
*/
void onLoadFailed(@Nullable Drawable errorDrawable);
/**
* Called when the resource is ready
* @param resource The loaded resource
* @param transition The transition to apply
*/
void onResourceReady(@NonNull R resource, @Nullable Transition<? super R> transition);
/**
* Called when the load is cleared
* @param placeholder The placeholder drawable to show
*/
void onLoadCleared(@Nullable Drawable placeholder);
/**
* Get the target size for the request
* @param cb Callback to receive the size
*/
void getSize(@NonNull SizeReadyCallback cb);
/**
* Remove a size callback
* @param cb The callback to remove
*/
void removeCallback(@NonNull SizeReadyCallback cb);
/**
* Set the request for this target
* @param request The request to associate
*/
void setRequest(@Nullable Request request);
/**
* Get the current request
* @return The associated request or null
*/
@Nullable Request getRequest();
}Targets follow a predictable lifecycle with well-defined callback methods:
// Example of target lifecycle flow
Target<Drawable> target = new CustomTarget<Drawable>() {
@Override
public void onLoadStarted(Drawable placeholder) {
// 1. Load begins - show placeholder
imageView.setImageDrawable(placeholder);
}
@Override
public void onResourceReady(Drawable resource, Transition transition) {
// 2. Success - apply resource and transition
imageView.setImageDrawable(resource);
if (transition != null) {
transition.transition(resource, new DrawableViewAdapter(imageView));
}
}
@Override
public void onLoadFailed(Drawable errorDrawable) {
// 3. Failure - show error drawable
imageView.setImageDrawable(errorDrawable);
}
@Override
public void onLoadCleared(Drawable placeholder) {
// 4. Cleared - cleanup and show placeholder
imageView.setImageDrawable(placeholder);
}
};Abstract base class for all ImageView-based targets providing common functionality.
public abstract class ImageViewTarget<Z> extends ViewTarget<ImageView, Z>
implements Transition.ViewAdapter {
/**
* Set the resource on the ImageView (implementation required)
* @param resource The resource to set
*/
protected abstract void setResource(@Nullable Z resource);
/**
* Get the current drawable from the ImageView
* @return The current drawable or null
*/
@Nullable
protected Drawable getCurrentDrawable() {
return view.getDrawable();
}
/**
* Set a drawable on the ImageView
* @param drawable The drawable to set
*/
protected void setDrawable(Drawable drawable) {
view.setImageDrawable(drawable);
}
@Override
public void onLoadStarted(@Nullable Drawable placeholder) {
super.onLoadStarted(placeholder);
setResourceInternal(null);
setDrawable(placeholder);
}
}Specialized target for loading Drawable resources into ImageViews.
public class DrawableImageViewTarget extends ImageViewTarget<Drawable> {
/**
* Constructor
* @param view The ImageView to load into
*/
public DrawableImageViewTarget(@NonNull ImageView view) {
super(view);
}
@Override
protected void setResource(@Nullable Drawable resource) {
view.setImageDrawable(resource);
}
}Specialized target for loading Bitmap resources into ImageViews.
public class BitmapImageViewTarget extends ImageViewTarget<Bitmap> {
/**
* Constructor
* @param view The ImageView to load into
*/
public BitmapImageViewTarget(@NonNull ImageView view) {
super(view);
}
@Override
protected void setResource(@Nullable Bitmap resource) {
view.setImageBitmap(resource);
}
}// Automatic target creation (recommended)
Glide.with(context)
.load("https://example.com/image.jpg")
.into(imageView);
// Explicit drawable target
DrawableImageViewTarget target = new DrawableImageViewTarget(imageView);
Glide.with(context)
.load("https://example.com/image.jpg")
.into(target);
// Explicit bitmap target
BitmapImageViewTarget bitmapTarget = new BitmapImageViewTarget(imageView);
Glide.with(context)
.asBitmap()
.load("https://example.com/image.jpg")
.into(bitmapTarget);Legacy target implementation - use CustomTarget instead.
@Deprecated
public abstract class SimpleTarget<Z> extends BaseTarget<Z> {
/**
* Constructor with specific dimensions
* @param width Target width
* @param height Target height
*/
public SimpleTarget(int width, int height) {
super(width, height);
}
/**
* Constructor using SIZE_ORIGINAL
*/
public SimpleTarget() {
this(SIZE_ORIGINAL, SIZE_ORIGINAL);
}
}Modern custom target implementation with proper lifecycle management.
public abstract class CustomTarget<T> implements Target<T> {
/**
* Constructor with specific dimensions
* @param width Target width in pixels
* @param height Target height in pixels
*/
public CustomTarget(int width, int height) {
this.width = width;
this.height = height;
}
/**
* Constructor using SIZE_ORIGINAL
*/
public CustomTarget() {
this(SIZE_ORIGINAL, SIZE_ORIGINAL);
}
/**
* Handle successful resource loading (implementation required)
* @param resource The loaded resource
* @param transition The transition to apply
*/
public abstract void onResourceReady(@NonNull T resource,
@Nullable Transition<? super T> transition);
/**
* Handle load clearing (implementation required)
* @param placeholder The placeholder drawable
*/
public abstract void onLoadCleared(@Nullable Drawable placeholder);
@Override
public final void getSize(@NonNull SizeReadyCallback cb) {
if (Util.isValidDimensions(width, height)) {
cb.onSizeReady(width, height);
return;
}
throw new IllegalArgumentException("Width and height must both be > 0 or Target#SIZE_ORIGINAL");
}
}// Basic custom target for drawable processing
CustomTarget<Drawable> drawableTarget = new CustomTarget<Drawable>() {
@Override
public void onResourceReady(@NonNull Drawable resource,
@Nullable Transition<? super Drawable> transition) {
// Process the loaded drawable
processDrawable(resource);
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
// Cleanup when cleared
clearProcessedData();
}
};
// Custom target with specific dimensions
CustomTarget<Bitmap> bitmapTarget = new CustomTarget<Bitmap>(500, 300) {
@Override
public void onResourceReady(@NonNull Bitmap resource,
@Nullable Transition<? super Bitmap> transition) {
// Use the 500x300 bitmap
saveBitmapToFile(resource);
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
// Cleanup temporary files
cleanupTempFiles();
}
};
// Loading into custom targets
Glide.with(context)
.load("https://example.com/image.jpg")
.into(drawableTarget);
Glide.with(context)
.asBitmap()
.load("https://example.com/image.jpg")
.override(500, 300)
.into(bitmapTarget);Target for loading images into notification RemoteViews.
public class NotificationTarget extends CustomTarget<Bitmap> {
/**
* Constructor
* @param context Application context
* @param viewId The view ID in the RemoteViews
* @param remoteViews The RemoteViews to update
* @param notification The notification to update
* @param notificationId The notification ID
* @param notificationTag The notification tag (optional)
*/
public NotificationTarget(Context context,
int viewId,
RemoteViews remoteViews,
Notification notification,
int notificationId,
@Nullable String notificationTag) {
super(SIZE_ORIGINAL, SIZE_ORIGINAL);
// Implementation details
}
/**
* Constructor without notification tag
*/
public NotificationTarget(Context context,
int viewId,
RemoteViews remoteViews,
Notification notification,
int notificationId) {
this(context, viewId, remoteViews, notification, notificationId, null);
}
}Target for loading images into app widget RemoteViews.
public class AppWidgetTarget extends CustomTarget<Bitmap> {
/**
* Constructor for single widget
* @param context Application context
* @param viewId The view ID in the RemoteViews
* @param remoteViews The RemoteViews to update
* @param appWidgetId The app widget ID
*/
public AppWidgetTarget(Context context,
int viewId,
RemoteViews remoteViews,
int appWidgetId) {
super(SIZE_ORIGINAL, SIZE_ORIGINAL);
// Implementation details
}
/**
* Constructor for multiple widgets
* @param context Application context
* @param viewId The view ID in the RemoteViews
* @param remoteViews The RemoteViews to update
* @param appWidgetIds Array of app widget IDs
*/
public AppWidgetTarget(Context context,
int viewId,
RemoteViews remoteViews,
int... appWidgetIds) {
super(SIZE_ORIGINAL, SIZE_ORIGINAL);
// Implementation details
}
}Target specifically designed for preloading resources into cache without displaying them.
public final class PreloadTarget<Z> extends CustomTarget<Z> {
/**
* Get a preload target for the given dimensions
* @param width Target width
* @param height Target height
* @return PreloadTarget instance
*/
public static <Z> PreloadTarget<Z> obtain(RequestManager requestManager,
int width,
int height) {
return new PreloadTarget<>(requestManager, width, height);
}
@Override
public void onResourceReady(@NonNull Z resource,
@Nullable Transition<? super Z> transition) {
// Resource is now in cache - no display needed
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
// Cleanup if needed
}
}// Notification target example
NotificationTarget notificationTarget = new NotificationTarget(
context,
R.id.notification_image,
remoteViews,
notification,
NOTIFICATION_ID
);
Glide.with(context)
.asBitmap()
.load("https://example.com/avatar.jpg")
.into(notificationTarget);
// App widget target example
AppWidgetTarget widgetTarget = new AppWidgetTarget(
context,
R.id.widget_image,
remoteViews,
appWidgetId
);
Glide.with(context)
.asBitmap()
.load("https://example.com/widget_image.jpg")
.into(widgetTarget);
// Preload target example
PreloadTarget<Drawable> preloadTarget = PreloadTarget.obtain(
Glide.with(context),
200, 200
);
Glide.with(context)
.load("https://example.com/image.jpg")
.into(preloadTarget);The primary method for loading resources into targets.
public class RequestBuilder<TranscodeType> {
/**
* Load into an ImageView (creates appropriate target automatically)
* @param view The ImageView to load into
* @return ViewTarget for the ImageView
*/
@NonNull
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
return into(glideContext.buildImageViewTarget(view, transcodeClass));
}
/**
* Load into a custom target
* @param target The target to load into
* @return The target (for chaining)
*/
@NonNull
public <Y extends Target<TranscodeType>> Y into(@NonNull Y target) {
return into(target, /*targetListener=*/ null, Executors.mainThreadExecutor());
}
/**
* Load into target with listener
* @param target The target to load into
* @param targetListener Listener for target events
* @return The target (for chaining)
*/
@NonNull
public <Y extends Target<TranscodeType>> Y into(@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener) {
return into(target, targetListener, Executors.mainThreadExecutor());
}
}For background loading without immediate display.
public class RequestBuilder<TranscodeType> {
/**
* Submit for background loading with original dimensions
* @return Future target for the request
*/
@NonNull
public FutureTarget<TranscodeType> submit() {
return submit(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL);
}
/**
* Submit for background loading with specific dimensions
* @param width Target width
* @param height Target height
* @return Future target for the request
*/
@NonNull
public FutureTarget<TranscodeType> submit(int width, int height) {
final RequestFutureTarget<TranscodeType> target =
new RequestFutureTarget<>(width, height);
return into(target, target, MoreExecutors.directExecutor());
}
}For preloading resources into cache.
public class RequestBuilder<TranscodeType> {
/**
* Preload with original dimensions
* @return PreloadTarget for the request
*/
@NonNull
public Target<TranscodeType> preload() {
return preload(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL);
}
/**
* Preload with specific dimensions
* @param width Target width for caching
* @param height Target height for caching
* @return PreloadTarget for the request
*/
@NonNull
public Target<TranscodeType> preload(int width, int height) {
final PreloadTarget<TranscodeType> target = PreloadTarget.obtain(requestManager, width, height);
return into(target);
}
}// Basic into() usage
Glide.with(context)
.load("https://example.com/image.jpg")
.into(imageView);
// Custom target with into()
CustomTarget<Bitmap> target = new CustomTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull Bitmap resource,
@Nullable Transition<? super Bitmap> transition) {
processImage(resource);
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
cleanup();
}
};
Glide.with(context)
.asBitmap()
.load("https://example.com/image.jpg")
.into(target);
// Background loading with submit()
FutureTarget<File> future = Glide.with(context)
.asFile()
.load("https://example.com/image.jpg")
.submit();
try {
File file = future.get(10, TimeUnit.SECONDS);
// Process downloaded file
} catch (Exception e) {
// Handle timeout or error
} finally {
Glide.with(context).clear(future);
}
// Preloading for cache
Glide.with(context)
.load("https://example.com/image.jpg")
.preload(200, 200);
// Later, load from cache
Glide.with(context)
.load("https://example.com/image.jpg")
.override(200, 200)
.into(imageView); // Will load from cache if availableSynchronous loading target that implements Future interface.
public class RequestFutureTarget<R> extends CustomTarget<R>
implements FutureTarget<R>, RequestListener<R> {
/**
* Get the result (blocking)
* @return The loaded resource
* @throws ExecutionException If loading failed
* @throws InterruptedException If interrupted
*/
@Override
public R get() throws InterruptedException, ExecutionException {
try {
return doGet(null);
} catch (TimeoutException e) {
throw new AssertionError(e);
}
}
/**
* Get the result with timeout
* @param time Maximum time to wait
* @param unit Time unit
* @return The loaded resource
* @throws ExecutionException If loading failed
* @throws InterruptedException If interrupted
* @throws TimeoutException If timeout exceeded
*/
@Override
public R get(long time, @NonNull TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
return doGet(unit.toMillis(time));
}
/**
* Cancel the request
* @param mayInterruptIfRunning Whether to interrupt if running
* @return true if successfully cancelled
*/
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
synchronized (this) {
if (isDone()) {
return false;
}
cancelled = true;
waiter.notifyAll();
if (mayInterruptIfRunning) {
clear();
}
return true;
}
}
/**
* Check if the request is cancelled
* @return true if cancelled
*/
@Override
public boolean isCancelled() {
synchronized (this) {
return cancelled;
}
}
/**
* Check if the request is done
* @return true if completed or cancelled
*/
@Override
public boolean isDone() {
synchronized (this) {
return cancelled || resultReceived || loadFailed;
}
}
}public interface Target<R> {
/**
* Indicates that the target wants the original image dimensions
*/
int SIZE_ORIGINAL = Integer.MIN_VALUE;
}public interface SizeReadyCallback {
/**
* Called when the target size is ready
* @param width The target width
* @param height The target height
*/
void onSizeReady(int width, int height);
}// Custom target with dynamic size calculation
CustomTarget<Drawable> dynamicTarget = new CustomTarget<Drawable>() {
@Override
public void getSize(@NonNull SizeReadyCallback cb) {
// Calculate size based on screen dimensions
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
int width = metrics.widthPixels / 2;
int height = metrics.heightPixels / 3;
cb.onSizeReady(width, height);
}
@Override
public void onResourceReady(@NonNull Drawable resource,
@Nullable Transition<? super Drawable> transition) {
// Handle dynamically sized resource
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
// Cleanup
}
};
// Using SIZE_ORIGINAL
CustomTarget<Bitmap> originalSizeTarget = new CustomTarget<Bitmap>(
Target.SIZE_ORIGINAL,
Target.SIZE_ORIGINAL
) {
// Implementation
};// Clear specific target
Target<Drawable> target = // ... create target
Glide.with(context)
.load("https://example.com/image.jpg")
.into(target);
// Later, clear the target
Glide.with(context).clear(target);
// Clear ImageView (automatic target)
Glide.with(context).clear(imageView);
// Clear all requests for a RequestManager
RequestManager requestManager = Glide.with(activity);
requestManager.clear(target1);
requestManager.clear(target2);
// Or pause all requests
requestManager.pauseRequests();public class MyActivity extends Activity {
private CustomTarget<Drawable> target;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
target = new CustomTarget<Drawable>() {
@Override
public void onResourceReady(@NonNull Drawable resource,
@Nullable Transition<? super Drawable> transition) {
// Use WeakReference for Activity context if needed
Activity activity = activityRef.get();
if (activity != null && !activity.isFinishing()) {
// Process resource
}
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
// Cleanup
}
};
Glide.with(this)
.load("https://example.com/image.jpg")
.into(target);
}
@Override
protected void onDestroy() {
// Clear target to prevent memory leaks
Glide.with(this).clear(target);
super.onDestroy();
}
}// Pool custom targets for performance
public class TargetPool {
private final Queue<CustomTarget<Bitmap>> pool = new ArrayDeque<>();
public CustomTarget<Bitmap> obtain() {
CustomTarget<Bitmap> target = pool.poll();
if (target == null) {
target = createNewTarget();
}
return target;
}
public void release(CustomTarget<Bitmap> target) {
// Reset target state
target.clear();
pool.offer(target);
}
private CustomTarget<Bitmap> createNewTarget() {
return new CustomTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull Bitmap resource,
@Nullable Transition<? super Bitmap> transition) {
// Process bitmap
processBitmap(resource);
// Return to pool when done
TargetPool.this.release(this);
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
// Cleanup
}
};
}
}// Target that delegates to multiple other targets
public class CompositeTarget<T> extends CustomTarget<T> {
private final List<Target<T>> targets;
public CompositeTarget(Target<T>... targets) {
this.targets = Arrays.asList(targets);
}
@Override
public void onLoadStarted(@Nullable Drawable placeholder) {
for (Target<T> target : targets) {
target.onLoadStarted(placeholder);
}
}
@Override
public void onResourceReady(@NonNull T resource,
@Nullable Transition<? super T> transition) {
for (Target<T> target : targets) {
target.onResourceReady(resource, transition);
}
}
@Override
public void onLoadFailed(@Nullable Drawable errorDrawable) {
for (Target<T> target : targets) {
target.onLoadFailed(errorDrawable);
}
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
for (Target<T> target : targets) {
target.onLoadCleared(placeholder);
}
}
@Override
public void getSize(@NonNull SizeReadyCallback cb) {
// Use the first target's size or provide default
if (!targets.isEmpty()) {
targets.get(0).getSize(cb);
} else {
cb.onSizeReady(SIZE_ORIGINAL, SIZE_ORIGINAL);
}
}
}This comprehensive documentation covers all aspects of Glide's target system and loading methods, providing developers with the complete API surface and practical usage patterns for implementing custom image loading destinations and managing the request lifecycle.
Install with Tessl CLI
npx tessl i tessl/maven-com-github-bumptech-glide--glide