Skip to content

Commit

Permalink
Expand exception handler to listen to load completion
Browse files Browse the repository at this point in the history
  • Loading branch information
sjudd committed Nov 6, 2013
1 parent f83b7e5 commit d216308
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 56 deletions.
57 changes: 37 additions & 20 deletions library/src/com/bumptech/glide/Glide.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import com.bumptech.glide.loader.transformation.None;
import com.bumptech.glide.loader.transformation.TransformationLoader;
import com.bumptech.glide.presenter.ImagePresenter;
import com.bumptech.glide.presenter.ImageReadyCallback;
import com.bumptech.glide.presenter.target.ImageViewTarget;
import com.bumptech.glide.presenter.target.Target;
import com.bumptech.glide.resize.ImageManager;
Expand Down Expand Up @@ -55,11 +54,11 @@ public class Glide {
private ImageManager imageManager = null;

/**
* A class for handling exceptions that occur while loading images
* A class for monitoring the status of a request while images load.
*
* @param <T> The type of the model being loaded
*/
public static abstract class ExceptionHandler<T> {
public static abstract class RequestListener<T> {

/**
* Called when an exception occurs during a load. Will only be called if we currently want to display an image
Expand Down Expand Up @@ -90,6 +89,15 @@ public static abstract class ExceptionHandler<T> {
*/
public abstract void onException(Exception e, T model, Target target);

/**
* Called when a load completes successfully, immediately before
* {@link Target#onImageReady(android.graphics.Bitmap)}.
*
* @param model The specific model that was used to load the image.
* @param target The target the model was loaded into.
*/
public abstract void onImageReady(T model, Target target);

/**
* {@inheritDoc}
*
Expand Down Expand Up @@ -484,7 +492,7 @@ public static class Request<T> {
private int errorId = -1;
private Downsampler downsampler = Downsampler.AT_LEAST;
private ArrayList<TransformationLoader<T>> transformationLoaders = new ArrayList<TransformationLoader<T>>();
private ExceptionHandler<T> exceptionHandler;
private RequestListener<T> requestListener;

private Request(T model) {
this(model, GLIDE.getFactory(model));
Expand Down Expand Up @@ -632,14 +640,15 @@ public Request<T> error(int resourceId) {
}

/**
* Sets an exception handler to use if a load fails. Note it's best to create a single instance of an exception
* handler per activity/fragment rather than pass one in per request.
* Sets a Request listener to monitor the image load. It's best to create a single instance of an exception
* handler per type of request (usually activity/fragment) rather than pass one in per request to avoid some
* redundant object allocation.
*
* @param exceptionHandler The exception handler to use
* @param requestListener The request listener to use
* @return This request
*/
public Request<T> exception(ExceptionHandler<T> exceptionHandler) {
this.exceptionHandler = exceptionHandler;
public Request<T> listener(RequestListener<T> requestListener) {
this.requestListener = requestListener;

return this;
}
Expand Down Expand Up @@ -725,14 +734,22 @@ private ImagePresenter<T> buildImagePresenter(final Target target) {
.setImageLoader(new ImageManagerLoader(context, downsampler))
.setTransformationLoader(transformationLoader);

if (animationId != -1) {
final Animation animation = AnimationUtils.loadAnimation(context, animationId);
builder.setImageReadyCallback(new ImageReadyCallback() {
if (animationId != -1 || requestListener != null) {
final Animation animation;
if (animationId != -1) {
animation = AnimationUtils.loadAnimation(context, animationId);
} else {
animation = null;
}
builder.setImageReadyCallback(new ImagePresenter.ImageReadyCallback<T>() {
@Override
public void onImageReady(Target target, boolean fromCache) {
if (!fromCache) {
public void onImageReady(T model, Target target, boolean fromCache) {
if (animation != null && !fromCache) {
target.startAnimation(animation);
}
if (requestListener != null) {
requestListener.onImageReady(null, target);
}
}
});
}
Expand All @@ -745,12 +762,12 @@ public void onImageReady(Target target, boolean fromCache) {
builder.setErrorResource(errorId);
}

if (exceptionHandler != null) {
if (requestListener != null) {
builder.setExceptionHandler(new ImagePresenter.ExceptionHandler<T>() {
@Override
public void onException(Exception e, T model, boolean isCurrent) {
if (isCurrent) {
exceptionHandler.onException(e, model, target);
requestListener.onException(e, model, target);
}
}
});
Expand Down Expand Up @@ -818,7 +835,7 @@ private static class Metadata {

private final String downsamplerId;
private final String transformationId;
private final ExceptionHandler exceptionHandler;
private final RequestListener requestListener;

public Metadata(Request request) {
modelClass = request.model.getClass();
Expand All @@ -828,7 +845,7 @@ public Metadata(Request request) {
animationId = request.animationId;
placeholderId = request.placeholderId;
errorId = request.errorId;
exceptionHandler = request.exceptionHandler;
requestListener = request.requestListener;
}

//we don't want to change behavior in sets/maps, just be able to compare properties
Expand All @@ -841,8 +858,8 @@ public boolean isIdenticalTo(Metadata metadata) {
if (!modelClass.equals(metadata.modelClass)) return false;
if (!modelLoaderClass.equals(metadata.modelLoaderClass)) return false;
if (!transformationId.equals(metadata.transformationId)) return false;
if (exceptionHandler == null ? metadata.exceptionHandler != null :
!exceptionHandler.equals(metadata.exceptionHandler)) return false;
if (requestListener == null ? metadata.requestListener != null :
!requestListener.equals(metadata.requestListener)) return false;

return true;
}
Expand Down
23 changes: 19 additions & 4 deletions library/src/com/bumptech/glide/presenter/ImagePresenter.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public class ImagePresenter<T> {
public static class Builder<T> {
private int placeholderResourceId;
private Drawable placeholderDrawable;
private ImageReadyCallback imageReadyCallback;
private ImageReadyCallback<T> imageReadyCallback;
private ImagePresenterCoordinator coordinator;
private ImageLoader imageLoader;
private Context context;
Expand Down Expand Up @@ -224,7 +224,7 @@ public Builder<T> setErrorDrawable(Drawable drawable) {
* @param cb The callback to call
* @return This Builder object
*/
public Builder<T> setImageReadyCallback(ImageReadyCallback cb) {
public Builder<T> setImageReadyCallback(ImageReadyCallback<T> cb) {
this.imageReadyCallback = cb;
return this;
}
Expand Down Expand Up @@ -281,7 +281,7 @@ public Builder<T> setTransformationLoader(TransformationLoader<T> transformation
private final TransformationLoader<T> transformationLoader;

private final Drawable placeholderDrawable;
private final ImageReadyCallback imageReadyCallback;
private final ImageReadyCallback<T> imageReadyCallback;
private final ImagePresenterCoordinator coordinator;
private final ExceptionHandler<T> exceptionHandler;

Expand Down Expand Up @@ -332,6 +332,21 @@ public interface ExceptionHandler<T> {
public void onException(Exception e, T model, boolean isCurrent);
}

/**
* A callback interface used to perform some action when an {@link ImagePresenter} sets a new bitmap in an
* {@link android.widget.ImageView}
*/
public interface ImageReadyCallback<T> {

/**
* The method called when a bitmap is set
*
* @param target The target that will display the bitmap
* @param fromCache True iff the load completed without a placeholder being shown.
*/
public void onImageReady(T model, Target target, boolean fromCache);
}

protected ImagePresenter(Builder<T> builder) {
this.imageLoader = builder.imageLoader;
this.transformationLoader = builder.transformationLoader;
Expand Down Expand Up @@ -439,7 +454,7 @@ public boolean onImageReady(Bitmap image) {
if (loadCount != currentCount || !canSetImage() || image == null) return false;

if (imageReadyCallback != null)
imageReadyCallback.onImageReady(target, loadedFromCache);
imageReadyCallback.onImageReady(model, target, loadedFromCache);
target.onImageReady(image);
isImageSet = true;
return true;
Expand Down
22 changes: 0 additions & 22 deletions library/src/com/bumptech/glide/presenter/ImageReadyCallback.java

This file was deleted.

15 changes: 11 additions & 4 deletions library/tests/src/com/bumptech/glide/GlideTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -214,19 +214,27 @@ public void testDifferentErrorIdsReplacesPresenter() {
);
}

public void testDifferentExceptionHandlersReplacesPresenter() {
public void testDifferentRequestListenersReplacesPresenter() {
assertDifferentPresenters(
Glide.load("a").exception(new Glide.ExceptionHandler<String>() {
Glide.load("a").listener(new Glide.RequestListener<String>() {

@Override
public void onException(Exception e, String model, Target target) {

}

@Override
public void onImageReady(String model, Target target) {
}
}),
Glide.load("a").exception(new Glide.ExceptionHandler<String>() {
Glide.load("a").listener(new Glide.RequestListener<String>() {
@Override
public void onException(Exception e, String model, Target target) {
}

@Override
public void onImageReady(String model, Target target) {
}
})
);
}
Expand All @@ -244,5 +252,4 @@ private void assertDifferentPresenters(Glide.Request a, Glide.Request b) {
assertSame(first, second);
assertNotSame(first, third);
}

}
5 changes: 2 additions & 3 deletions library/tests/src/com/bumptech/glide/ImagePresenterTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import com.bumptech.glide.loader.model.ModelLoader;
import com.bumptech.glide.loader.stream.StreamLoader;
import com.bumptech.glide.presenter.ImagePresenter;
import com.bumptech.glide.presenter.ImageReadyCallback;
import com.bumptech.glide.presenter.target.Target;
import com.bumptech.glide.resize.load.Transformation;

Expand Down Expand Up @@ -330,9 +329,9 @@ public void onCallbackReceived(ImageLoader.ImageReadyCallback cb) {
cb.onImageReady(Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_4444));
}
}))
.setImageReadyCallback(new ImageReadyCallback() {
.setImageReadyCallback(new ImagePresenter.ImageReadyCallback<Object>() {
@Override
public void onImageReady(Target target, boolean fromCache) {
public void onImageReady(Object model, Target target, boolean fromCache) {
wasImageSetCallbackCalled.set(true);
}
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import com.bumptech.glide.loader.model.Cache;
import com.bumptech.glide.loader.transformation.CenterCrop;
import com.bumptech.glide.presenter.ImagePresenter;
import com.bumptech.glide.presenter.ImageReadyCallback;
import com.bumptech.glide.presenter.target.Target;
import com.bumptech.glide.samples.flickr.api.Photo;

Expand Down Expand Up @@ -118,9 +117,9 @@ public View getView(int position, View view, ViewGroup container) {
.setImageView(imageView)
.setImageLoader(new ImageManagerLoader(context))
.setTransformationLoader(new CenterCrop<Photo>())
.setImageReadyCallback(new ImageReadyCallback() {
.setImageReadyCallback(new ImagePresenter.ImageReadyCallback<Photo>() {
@Override
public void onImageReady(Target target, boolean fromCache) {
public void onImageReady(Photo photo, Target target, boolean fromCache) {
if (!fromCache) {
target.startAnimation(fadeIn);
}
Expand Down

0 comments on commit d216308

Please sign in to comment.