Skip to content

Commit b3b2d7a

Browse files
committedSep 21, 2018
Add a CustomTarget class
Extending Target directly requires implementing some not totally trivial boilerplate logic in set/getRequest and getSize. This class does not implement onLoadCleared, and should provide an implementation safer than BaseTarget and SimpleTarget, but more convenient than just the Target interface. See #3304 for an example request for this class. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=212743879
1 parent b456290 commit b3b2d7a

File tree

3 files changed

+131
-7
lines changed

3 files changed

+131
-7
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
package com.bumptech.glide.request.target;
2+
3+
import android.graphics.Bitmap;
4+
import android.graphics.drawable.Drawable;
5+
import android.support.annotation.NonNull;
6+
import android.support.annotation.Nullable;
7+
import android.view.View;
8+
import android.widget.ImageView;
9+
import com.bumptech.glide.request.Request;
10+
import com.bumptech.glide.request.transition.Transition;
11+
import com.bumptech.glide.util.Util;
12+
13+
/**
14+
* A base {@link Target} for loading resources ({@link android.graphics.Bitmap}, {@link Drawable}
15+
* etc) that are used outside of {@link android.view.View}s.
16+
*
17+
* <p>If you're loading a resource into a {@link View}, use
18+
* {@link com.bumptech.glide.RequestBuilder#into(ImageView)}, a subclass of {@link ImageViewTarget},
19+
* or {@link CustomViewTarget}. Using this class to load resources into {@link View}s can prevent
20+
* Glide from correctly cancelling any previous loads, which may result in incorrect images
21+
* appearing in the view, especially in scrolling views like
22+
* {@link android.support.v7.widget.RecyclerView}.
23+
*
24+
* <p>You <em>MUST</em> implement {@link #onLoadCleared(Drawable)} and ensure that all references to
25+
* any resource passed into the target in {@link #onResourceReady(Object, Transition)} are removed
26+
* before {@link #onLoadCleared(Drawable)} completes. Failing to do so can result in graphical
27+
* corruption, crashes caused by recycled {@link Bitmap}s, and other undefined behavior. It is never
28+
* safe to leave {@link #onLoadCleared(Drawable)} unimplemented or empty. Even if you do not
29+
* manually clear this {@link Target}, Glide may do so automatically after certain lifecycle events
30+
* in {@link android.support.v4.app.Fragment}s and {@link android.app.Activity}s.
31+
*
32+
* <p>This class can only be used with {@link Target#SIZE_ORIGINAL} or when the desired resource
33+
* dimensions are known when the {@link Target} is created. If you'd like to run some asynchronous
34+
* process and make full use of {@link #getSize(SizeReadyCallback)} and {@link SizeReadyCallback},
35+
* extend {@link Target} directly instead of using this class.
36+
*
37+
* @param <T> The type of resource that will be loaded (e.g. {@link Bitmap}).
38+
*/
39+
public abstract class CustomTarget<T> implements Target<T> {
40+
41+
private final int width;
42+
private final int height;
43+
44+
@Nullable
45+
private Request request;
46+
47+
/**
48+
* Creates a new {@link CustomTarget} that will attempt to load the resource in its original size.
49+
*
50+
* <p>This constructor can cause very memory inefficient loads if the resource is large and can
51+
* cause OOMs. It's provided as a convenience for when you'd like to specify dimensions with
52+
* {@link com.bumptech.glide.request.RequestOptions#override(int)}. In all other cases, prefer
53+
* {@link #CustomTarget(int, int)}.
54+
*/
55+
public CustomTarget() {
56+
this(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL);
57+
}
58+
59+
/**
60+
* Creates a new {@code CustomTarget} that will return the given {@code width} and {@link @code}
61+
* as the requested size (unless overridden by
62+
* {@link com.bumptech.glide.request.RequestOptions#override(int)} in the request).
63+
*
64+
* @param width The requested width (>= 0, or == Target.SIZE_ORIGINAL).
65+
* @param height The requested height (>= 0, or == Target.SIZE_ORIGINAL).
66+
*/
67+
public CustomTarget(int width, int height) {
68+
if (!Util.isValidDimensions(width, height)) {
69+
throw new IllegalArgumentException(
70+
"Width and height must both be > 0 or Target#SIZE_ORIGINAL, but given" + " width: "
71+
+ width + " and height: " + height);
72+
}
73+
74+
this.width = width;
75+
this.height = height;
76+
}
77+
78+
@Override
79+
public void onStart() {
80+
// Intentionally empty, this can be optionally implemented by subclasses.
81+
}
82+
83+
@Override
84+
public void onStop() {
85+
// Intentionally empty, this can be optionally implemented by subclasses.
86+
}
87+
88+
@Override
89+
public void onDestroy() {
90+
// Intentionally empty, this can be optionally implemented by subclasses.
91+
}
92+
93+
@Override
94+
public void onLoadStarted(@Nullable Drawable placeholder) {
95+
// Intentionally empty, this can be optionally implemented by subclasses.
96+
}
97+
98+
@Override
99+
public void onLoadFailed(@Nullable Drawable errorDrawable) {
100+
// Intentionally empty, this can be optionally implemented by subclasses.
101+
}
102+
103+
@Override
104+
public final void getSize(@NonNull SizeReadyCallback cb) {
105+
cb.onSizeReady(width, height);
106+
}
107+
108+
@Override
109+
public final void removeCallback(@NonNull SizeReadyCallback cb) {
110+
// Do nothing, this class does not retain SizeReadyCallbacks.
111+
}
112+
113+
@Override
114+
public final void setRequest(@Nullable Request request) {
115+
this.request = request;
116+
}
117+
118+
@Nullable
119+
@Override
120+
public final Request getRequest() {
121+
return request;
122+
}
123+
}

‎library/src/main/java/com/bumptech/glide/request/target/CustomViewTarget.java

+6-5
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,13 @@
2424
import java.util.List;
2525

2626
/**
27-
* A base {@link Target} for loading {@link android.graphics.Bitmap}s into {@link View}s that
28-
* provides default implementations for most methods and can determine the size of views using a
29-
* {@link android.view.ViewTreeObserver.OnDrawListener}.
27+
* A base {@link Target} for loading resources ({@link android.graphics.Bitmap}, {@link Drawable}
28+
* etc) into {@link View}s that provides default implementations for most methods and can determine
29+
* the size of views using a {@link android.view.ViewTreeObserver.OnDrawListener}.
3030
*
31-
* @param <T> The specific subclass of view wrapped by this target.
32-
* @param <Z> The resource type this target will receive.
31+
* @param <T> The specific subclass of view wrapped by this target (e.g.
32+
* {@link android.widget.ImageView})
33+
* @param <Z> The resource type this target will receive (e.g. {@link android.graphics.Bitmap}).
3334
*/
3435
public abstract class CustomViewTarget<T extends View, Z> implements Target<Z> {
3536
private static final String TAG = "CustomViewTarget";

‎library/src/main/java/com/bumptech/glide/request/target/SimpleTarget.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@
6161
* @param <Z> The type of resource that this target will receive.
6262
* @deprecated Use {@link CustomViewTarget} if loading the content into a view, the download API if
6363
* in the background
64-
* (http://bumptech.github.io/glide/doc/getting-started.html#background-threads), or a a fully
65-
* implemented {@link Target} for any specialized use-cases. Using BaseView is unsafe if the
64+
* (http://bumptech.github.io/glide/doc/getting-started.html#background-threads), or a
65+
* {@link CustomTarget} for any specialized use-cases. Using BaseView is unsafe if the
6666
* user does not implement {@link #onLoadCleared}, resulting in recycled bitmaps being
6767
* referenced from the UI and hard to root-cause crashes.
6868
*/

0 commit comments

Comments
 (0)