Continued from template mode 1 of Glide design mode
The list of known implementation classes of LifecycleListener is as follows:
- AppWidgetTarget
- BaseTarget
- BitmapImageViewTarget
- BitmapThumbnailImageViewTarget
- CustomTarget
- CustomViewTarget
- DrawableImageViewTarget
- DrawableThumbnailImageViewTarget
- ImageViewTarget
- NotificationTarget
- PreloadTarget
- RequestFutureTarget
- RequestManager
- SimpleTarget
- TargetTracker
- ThumbnailImageViewTarget
- ViewTarget
DrawableThumbnailImageViewTarget
com.bumptech.glide.request.target.DrawableThumbnailImageViewTarget
Efficiently display multiple Drawables that are continuously loaded into a view.
/** * Efficiently displays multiple Drawables loaded serially into a single {@link android.view.View}. */ Efficiently display multiple views that are continuously loaded into one view Drawables. // Public API. @SuppressWarnings("unused") public class DrawableThumbnailImageViewTarget extends ThumbnailImageViewTarget<Drawable> { public DrawableThumbnailImageViewTarget(ImageView view) { super(view); } /** @deprecated Use {@link #waitForLayout()} instead. */ @Deprecated @SuppressWarnings("deprecation") public DrawableThumbnailImageViewTarget(ImageView view, boolean waitForLayout) { super(view, waitForLayout); } @Override protected Drawable getDrawable(Drawable resource) { return resource; } }
NotificationTarget
com.bumptech.glide.request.target.NotificationTarget
This class is used to display the downloaded bitmap in a notified ImageView through RemoteViews.
Note: for cancellation to work properly, you must pass in the same instance of this class every subsequent load.
/** * This class is used to display downloaded Bitmap inside an ImageView of a Notification through * RemoteViews. * * <p>Note - For cancellation to work correctly, you must pass in the same instance of this class * for every subsequent load. */ This class is used to pass RemoteViews In a notification ImageView Displays the downloaded bitmap in. be careful:For cancellation to work properly, you must pass in the same instance of this class every subsequent load. // Public API. @SuppressWarnings({"WeakerAccess", "unused"}) public class NotificationTarget extends CustomTarget<Bitmap> {
PreloadTarget
com.bumptech.glide.request.target.PreloadTarget
A one-time Target class that loads resources into memory and then clears itself.
/** * A one time use {@link com.bumptech.glide.request.target.Target} class that loads a resource into * memory and then clears itself. * * @param <Z> The type of resource that will be loaded into memory. */ Disposable Target Class, which loads resources into memory and then clears itself public final class PreloadTarget<Z> extends CustomTarget<Z> { private static final int MESSAGE_CLEAR = 1; private static final Handler HANDLER = new Handler( Looper.getMainLooper(), new Callback() { @Override public boolean handleMessage(Message message) { if (message.what == MESSAGE_CLEAR) { ((PreloadTarget<?>) message.obj).clear(); return true; } return false; } }); private final RequestManager requestManager; /** * Returns a PreloadTarget. * * @param width The width in pixels of the desired resource. * @param height The height in pixels of the desired resource. * @param <Z> The type of the desired resource. */ public static <Z> PreloadTarget<Z> obtain(RequestManager requestManager, int width, int height) { return new PreloadTarget<>(requestManager, width, height); } private PreloadTarget(RequestManager requestManager, int width, int height) { super(width, height); this.requestManager = requestManager; } @Override public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) { // If a thumbnail request is set and the thumbnail completes, we don't want to cancel the // primary load. Instead we wait until the primary request (the one set on the target) says // that it is complete. // Note - Any thumbnail request that does not complete before the primary request will be // cancelled and may not be preloaded successfully. Cancellation of outstanding thumbnails after // the primary request succeeds is a common behavior of all Glide requests and we're not trying // to override it here. Request request = getRequest(); if (request != null && request.isComplete()) { HANDLER.obtainMessage(MESSAGE_CLEAR, this).sendToTarget(); } } @Override public void onLoadCleared(@Nullable Drawable placeholder) { // Do nothing, we don't retain a reference to our resource. } @SuppressWarnings("WeakerAccess") @Synthetic void clear() { requestManager.clear(this); } }
RequestFutureTarget
com.bumptech.glide.request.RequestFutureTarget
A future Glide implementation, which can be used to load resources in a blocking manner in the background thread
/** * A {@link java.util.concurrent.Future} implementation for Glide that can be used to load resources * in a blocking manner on background threads. * * <p>Note - Unlike most targets, RequestFutureTargets can be used once and only once. Attempting to * reuse a RequestFutureTarget will probably result in undesirable behavior or exceptions. Instead * of reusing objects of this class, the pattern should be: * * <pre>{@code * FutureTarget<File> target = null; * RequestManager requestManager = Glide.with(context); * try { * target = requestManager * .downloadOnly() * .load(model) * .submit(); * File downloadedFile = target.get(); * // ... do something with the file (usually throws IOException) * } catch (ExecutionException | InterruptedException | IOException e) { * // ... bug reporting or recovery * } finally { * // make sure to cancel pending operations and free resources * if (target != null) { * target.cancel(true); // mayInterruptIfRunning * } * } * }</pre> * * The {@link #cancel(boolean)} call will cancel pending operations and make sure that any resources * used are recycled. * * @param <R> The type of the resource that will be loaded. */ A future Glide Implementation, which can be used to load resources in a blocking manner in the background thread. be careful:Unlike most goals, RequestFutureTargets Can only be used once. Try to reuse RequestFutureTarget May lead to bad behavior or abnormalities. Instead of reusing objects of this class, the pattern should be: FutureTarget<file>target= null; RequestManager RequestManager = Glide.with(context); attempt{ target= requestManager .downloadOnly () .load(Model) . submit (); filedownloaddfile = target.get(); / /......Do something about the file(Usually throw IOException) } catch (ExecutionException | InterruptedException | IOException e) { / /......Bug Report or repair last}{ //Make sure to cancel pending operations and free resources If (target != null) { target.cancel(real);/ / mayInterruptIfRunning } } cancel(boolean)The call cancels the pending operation and ensures that all used resources are recycled. public class RequestFutureTarget<R> implements FutureTarget<R>, RequestListener<R> {
FutureTarget
com.bumptech.glide.request.FutureTarget
An interface that is both a goal and a future object
/** * An interface for an object that is both a {@link com.bumptech.glide.request.target.Target} and a * {@link java.util.concurrent.Future}. For example: * * <pre>{@code * FutureTarget<Bitmap> futureTarget = Glide.with(fragment) * .load("http://goo.gl/1asf12") * .asBitmap() * .into(250, 250); * Bitmap myBitmap = futureTarget.get(); * ... // do things with bitmap and then release when finished: * futureTarget.cancel(false); * }</pre> * * <p>Note - {@link #get()} and {@link #get(long, java.util.concurrent.TimeUnit)} must be called off * of the main thread or they will block forever. * * @param <R> The type of resource this FutureTarget will retrieve. */ An interface that is both a goal and a future object. for example: FutureTarget<Bitmap> FutureTarget = Glide.with(fragment) .load("http://goo.gl/1asf12") .asBitmap () .into(250,250); Bitmap myBitmap = futureTarget.get(); ... //Use bitmap to do things, and then release when finished: futureTarget.cancel(false); be careful- Future.get()and Future. get(long, java.util.concurrent.TimeUnit)Must be invoked from the main thread, otherwise they will always block. public interface FutureTarget<R> extends Future<R>, Target<R> {}
RequestManager
com.bumptech.glide.RequestManager
Class used to manage and start Glide requests. You can use Activity, Fragment, and connection lifecycle events to intelligently stop, start, and restart requests. Retrieve by instantiating a new object, or use the built-in Activity and Fragment life cycle processing to use the static Glide. Load methods with Fragment or Activity.
/** * A class for managing and starting requests for Glide. Can use activity, fragment and connectivity * lifecycle events to intelligently stop, start, and restart requests. Retrieve either by * instantiating a new object, or to take advantage built in Activity and Fragment lifecycle * handling, use the static Glide.load methods with your Fragment or Activity. * * @see Glide#with(android.app.Activity) * @see Glide#with(androidx.fragment.app.FragmentActivity) * @see Glide#with(android.app.Fragment) * @see Glide#with(androidx.fragment.app.Fragment) * @see Glide#with(Context) */ For management and startup Glide The requested class. You can use activity, fragment, and connection lifecycle events to intelligently stop, start, and restart requests. Retrieve by instantiating a new object, or use the built-in Activity and Fragment Lifecycle processing, using static Glide. use Fragment or Activity Loading method. public class RequestManager implements ComponentCallbacks2, LifecycleListener, ModelTypes<RequestBuilder<Drawable>> { private static final RequestOptions DECODE_TYPE_BITMAP = decodeTypeOf(Bitmap.class).lock(); private static final RequestOptions DECODE_TYPE_GIF = decodeTypeOf(GifDrawable.class).lock(); private static final RequestOptions DOWNLOAD_ONLY_OPTIONS = diskCacheStrategyOf(DiskCacheStrategy.DATA).priority(Priority.LOW).skipMemoryCache(true); protected final Glide glide; protected final Context context; @SuppressWarnings("WeakerAccess") @Synthetic final Lifecycle lifecycle; @GuardedBy("this") private final RequestTracker requestTracker; @GuardedBy("this") private final RequestManagerTreeNode treeNode; @GuardedBy("this") private final TargetTracker targetTracker = new TargetTracker(); private final Runnable addSelfToLifecycle = new Runnable() { @Override public void run() { lifecycle.addListener(RequestManager.this); } }; /** * Lifecycle callback that registers for connectivity events (if the * android.permission.ACCESS_NETWORK_STATE permission is present) and restarts failed or paused * requests. */ @Override public synchronized void onStart() { resumeRequests(); targetTracker.onStart(); } /** * Lifecycle callback that unregisters for connectivity events (if the * android.permission.ACCESS_NETWORK_STATE permission is present) and pauses in progress loads. */ @Override public synchronized void onStop() { pauseRequests(); targetTracker.onStop(); } /** * Lifecycle callback that cancels all in progress requests and clears and recycles resources for * all completed requests. */ @Override public synchronized void onDestroy() { targetTracker.onDestroy(); for (Target<?> target : targetTracker.getAll()) { clear(target); } targetTracker.clear(); requestTracker.clearRequests(); lifecycle.removeListener(this); lifecycle.removeListener(connectivityMonitor); Util.removeCallbacksOnUiThread(addSelfToLifecycle); glide.unregisterRequestManager(this); }
RequestManager is a complex class. There are a lot of business logic involved. This paper only focuses on the implementation after the integration of interfaces and abstract classes, and focuses on the business implementation of template mode. Easy to understand
SimpleTarget
com.bumptech.glide.request.target.SimpleTarget
A simple Target base class with a default (usually no OP) implementation of a non basic method that allows the caller to specify the exact width / height.
Deprecated
/** * A simple {@link com.bumptech.glide.request.target.Target} base class with default (usually no-op) * implementations of non essential methods that allows the caller to specify an exact width/height. * Typically use cases look something like this: * * <pre> * <code> * Target<Bitmap> target = * Glide.with(fragment) * .asBitmap() * .load("http://somefakeurl.com/fakeImage.jpeg") * .apply(fitCenterTransform()) * .into(new SimpleTarget<Bitmap>(250, 250) { * * {@literal @Override} * public void onResourceReady(Bitmap resource, Transition<? super Bitmap> transition) { * // Do something with bitmap here. * } * * }); * } * // At some later point, clear the Target to release the resources, prevent load queues from * // blowing out proportion, and to improve load times for future requests: * Glide.with(fragment).clear(target); * </code> * </pre> * * <p><em>Warning!</em> this class is extremely prone to mis-use. Use SimpleTarget only as a last * resort. {@link ViewTarget} or a subclass of {@link ViewTarget} is almost always a better choice. * * <p><em>Don't forget to clear instances of this class!</em>. If you must use this class, keep in * mind that unlike {@link ViewTarget} it is not safe to load into new instances of this class * repeatedly if every instance updates the same underlying {@link View} or caller. If you need to * load into the same {@link View} or caller repeatedly using this class, always retain a reference * to the previous instance and either call {@link com.bumptech.glide.RequestManager#clear(Target)} * on the old instance before starting a new load or you must re-use the old instance for the new * load. Glide's {@link com.bumptech.glide.RequestBuilder#into(Target)} method returns the {@link * Target} instance you provided to make retaining a reference to the {@link Target} as easy as * possible. That said, you must wait until you're completely finished with the resource before * calling {@link com.bumptech.glide.RequestManager#clear(Target)} and you should always null out * references to any loaded resources in {@link Target#onLoadCleared(Drawable)}. * * <p>Always try to provide a size when using this class. Use {@link SimpleTarget#SimpleTarget(int, * int)} whenever possible with values that are <em>not</em> {@link Target#SIZE_ORIGINAL}. Using * {@link Target#SIZE_ORIGINAL} is unsafe if you're loading large images or are running your * application on older or memory constrained devices because it can cause Glide to load very large * images into memory. In some cases those images may throw {@link OutOfMemoryError} and in others * they may exceed the texture limit for the device, which will prevent them from being rendered. * Providing a valid size allows Glide to downsample large images, which can avoid issues with * texture size or memory limitations. You don't have to worry about providing a size in most cases * if you use {@link ViewTarget} so prefer {@link ViewTarget} over this class whenver possible. * * @see <a href="http://bumptech.github.io/glide/doc/targets.html">Glide's Target docs page</a> * @param <Z> The type of resource that this target will receive. * @deprecated Use {@link CustomViewTarget} if loading the content into a view, the download API if * in the background * (http://bumptech.github.io/glide/doc/getting-started.html#background-threads), or a {@link * CustomTarget} for any specialized use-cases. Using {@link SimpleTarget} or {@link BaseTarget} * is unsafe if the user does not implement {@link #onLoadCleared}, resulting in recycled * bitmaps being referenced from the UI and hard to root-cause crashes. */ A simple Target Base class with default of non basic method(Usually no-op)Implementation that allows the caller to specify the exact width/Height. A typical use case looks like this: Target target= Glide.with(fragment) .asBitmap () .load("http://somefakeurl.com/fakeImage.jpeg") Apple(fitCenterTransform ()) .into(new SimpleTarget(250, 250)) { @Override public void onResourceReady(Bitmap resource, transition){ //Do something about bitmap. } }); } //Later, clear the Target to free up resources and prevent the load queue from moving from //Blow out ratio and improve loading time for future requests: Glide.with(fragment).clear(target); warning!This class is easily misused. use SimpleTarget Only as a last resort. ViewTarget or ViewTarget Subclasses of are almost always a better choice. Don't forget to clear instances of this class!If you have to use this class, remember, and ViewTarget The difference is that if each instance updates the same underlying view or caller, it is not safe to repeatedly load into a new instance of this class. If you need to load into the same view or the caller uses this class repeatedly,Always keep a reference to the previous instance and call RequestManager.clear(target)Before the old instance,Start a new load or you must reuse the load of the old instance. Glide of RequestBuilder.into(Target)Method returns the target instance you provided so that it is as easy as possible to retain a reference to the target. That is, you have to wait until you complete the resource call RequestManager.clear(Target)Before that, you should always leave the right room Target. onloadcleared (Drawable)A reference to any loaded resource in. When using this class, always try to provide a size. Whenever possible, use SimpleTarget(int, int)To deal with it, No Target.SIZE_ORIGINAL Value of. Use target. If you are loading large images, or running applications on old or memory constrained devices, then SIZE_ORIGINAL Is unsafe because it can lead to Glide Load very large images into memory. In some cases, these images may be thrown OutOfMemoryError,In other cases, they may exceed the texture limit of the device, which prevents them from being rendered. Provide a valid size allowed Glide Sample larger images, which can avoid the problem of texture size or memory limitation. If you use ViewTarget,You don't have to worry about providing a size in most cases, so use it as much as possible ViewTarget Not this class. Discard. If you load content into a view, use CustomViewTarget;If you're backstage(http://bumptech. github. io/glide/doc/getting-started. HTML #background threads), then use the download API; For any specific use case, use CustomTarget. Using SimpleTarget or BaseTarget is not safe if the user does not implement basettarget Onloadcleared (Android. Graphics. Drawable. Drawable), resulting in recycled bitmaps being referenced from the UI and difficult to crash from the root cause. @Deprecated public abstract class SimpleTarget<Z> extends BaseTarget<Z> { private final int width; private final int height; /** * Constructor for the target that uses {@link Target#SIZE_ORIGINAL} as the target width and * height. */ // Public API. @SuppressWarnings("WeakerAccess") public SimpleTarget() { this(SIZE_ORIGINAL, SIZE_ORIGINAL); } /** * Constructor for the target that takes the desired dimensions of the decoded and/or transformed * resource. * * @param width The width in pixels of the desired resource. * @param height The height in pixels of the desired resource. */ // Public API. @SuppressWarnings("WeakerAccess") public SimpleTarget(int width, int height) { this.width = width; this.height = height; } /** * Immediately calls the given callback with the sizes given in the constructor. * * @param cb {@inheritDoc} */ @Override public final void getSize(@NonNull SizeReadyCallback cb) { if (!Util.isValidDimensions(width, height)) { throw new IllegalArgumentException( "Width and height must both be > 0 or Target#SIZE_ORIGINAL, but given" + " width: " + width + " and height: " + height + ", either provide dimensions in the constructor" + " or call override()"); } cb.onSizeReady(width, height); } @Override public void removeCallback(@NonNull SizeReadyCallback cb) { // Do nothing, we never retain a reference to the callback. } }
TargetTracker
com.bumptech.glide.manager.TargetTracker
Save the target set of the current activity for the RequestManager and forward the lifecycle events.
/** * Holds the set of {@link Target}s currently active for a {@link com.bumptech.glide.RequestManager} * and forwards on lifecycle events. */ by RequestManager Saves the target set of the current activity and forwards lifecycle events. public final class TargetTracker implements LifecycleListener { private final Set<Target<?>> targets = Collections.newSetFromMap(new WeakHashMap<Target<?>, Boolean>()); public void track(@NonNull Target<?> target) { targets.add(target); } public void untrack(@NonNull Target<?> target) { targets.remove(target); } @Override public void onStart() { for (Target<?> target : Util.getSnapshot(targets)) { target.onStart(); } } @Override public void onStop() { for (Target<?> target : Util.getSnapshot(targets)) { target.onStop(); } } @Override public void onDestroy() { for (Target<?> target : Util.getSnapshot(targets)) { target.onDestroy(); } } @NonNull public List<Target<?>> getAll() { return Util.getSnapshot(targets); } public void clear() { targets.clear(); } }
ThumbnailImageViewTarget
com.bumptech.glide.request.target.ThumbnailImageViewTarget
When loading multiple fixed size images into ImageView, avoid calling view requestLayout().
Usually, when using requestbuilder It makes sense to use this class when the thumbnail (COM. Bump technology. glide.requestbuilder) API loads multiple images into a view of a scrolling list (such as ListView, GridView, or RecyclerView).
Fixed sizeable can lead to tilting or other undesirable behavior, depending on your image, view, and zoom. If this happens, you can consider DrawableImageViewTarget or BitmapImageViewTarget as an alternative.
/** * Avoids extra calls to {@link android.view.View#requestLayout} when loading more than once image * into an {@link android.widget.ImageView} with fixed dimensions. * * <p>Typically it makes sense to use this class when loading multiple images with the {@link * com.bumptech.glide.RequestBuilder#thumbnail(com.bumptech.glide.RequestBuilder)} API into views in * a scrolling list like ListView, GridView, or RecyclerView. * * <p>{@link FixedSizeDrawable} may cause skewing or other undesirable behavior depending on your * images, views, and scaling. If this occurs, consider {@link DrawableImageViewTarget} or {@link * BitmapImageViewTarget} as alternatives. * * @param <T> The type of resource that will be displayed in the ImageView. */ When loading multiple fixed size images to ImageView Avoid extra calls when View.requestLayout(). Usually, when using RequestBuilder.thumbnail(com. bump Technology. glide.requestbuilder) API Load multiple images into the view of the scrolling list(as ListView, GridView,or RecyclerView)It makes sense to use this class. fixedsizerawable Depending on your image, view, and zoom, tilting or other undesirable behavior may result. If this happens, it can be considered DrawableImageViewTarget or BitmapImageViewTarget As an alternative. // Public API. @SuppressWarnings("WeakerAccess") public abstract class ThumbnailImageViewTarget<T> extends ImageViewTarget<T> { public ThumbnailImageViewTarget(ImageView view) { super(view); } /** @deprecated Use {@link #waitForLayout()} insetad. */ @Deprecated @SuppressWarnings({"deprecation"}) public ThumbnailImageViewTarget(ImageView view, boolean waitForLayout) { super(view, waitForLayout); } @Override protected void setResource(@Nullable T resource) { ViewGroup.LayoutParams layoutParams = view.getLayoutParams(); Drawable result = getDrawable(resource); if (layoutParams != null && layoutParams.width > 0 && layoutParams.height > 0) { result = new FixedSizeDrawable(result, layoutParams.width, layoutParams.height); } view.setImageDrawable(result); } protected abstract Drawable getDrawable(T resource); }
Summary
Glide's template pattern is complex to use, which is also determined by the business characteristics. The more inheritance levels of the behavior structure of the template pattern, the more complex it becomes; When you see complex template patterns, don't delve into business details first. First look at the business expressions of abstract classes and interfaces, and then sort them out according to the business expressions of interfaces and abstract classes, so as to find the main business line. Classes that implement several interfaces and business lines like RequestManager should be understood and parsed separately. Then make an overall understanding.