提交 8c7ae0d1 编写于 作者: S Sam Judd

Revamp Glide interface to be more flexible.

Conflicts:
	library/src/com/bumptech/glide/presenter/target/ImageViewTarget.java
上级 896af010
......@@ -193,8 +193,9 @@ public class Glide {
/**
* Use the given factory to build a {@link ModelLoader} for models of the given class. Generally the best use of
* this method is to replace one of the default factories or add an implementation for other similar low level
* models. Typically the {@link Glide#using(StreamModelLoader)} or {@link Glide#using(FileDescriptorModelLoader)}
* syntax is preferred because it directly links the model with the ModelLoader being used to load it.
* models. Typically the {@link ModelRequest#using(StreamModelLoader)} or
* {@link ModelRequest#using(FileDescriptorModelLoader)} syntax is preferred because it directly links the model
* with the ModelLoader being used to load it.
*
* <p>
* Note - If a factory already exists for the given class, it will be replaced. If that factory is not being
......@@ -207,8 +208,8 @@ public class Glide {
* retained statically.
* </p>
*
* @see #using(FileDescriptorModelLoader)
* @see #using(StreamModelLoader)
* @see ModelRequest#using(FileDescriptorModelLoader)
* @see ModelRequest#using(StreamModelLoader)
*
* @param modelClass The model class.
* @param resourceClass The resource class the model loader will translate the model type into.
......@@ -241,170 +242,163 @@ public class Glide {
return loaderFactory.getFactory((Class<T>) model.getClass(), resourceClass);
}
private ImageViewTarget getImageViewTarget(ImageView imageView) {
Object tag = imageView.getTag();
ImageViewTarget result = null;
if (tag instanceof ImageViewTarget) {
result = (ImageViewTarget) tag;
} else if (tag != null) {
throw new IllegalArgumentException("You cannot set a tag on an image view Glide is loading an image into");
/**
* Cancel any pending loads Glide may have for the target. After the load is cancelled Glide will not load
* a placeholder or bitmap into the target so it is safe to do so yourself until you start another load.
*
* @param target The Target to cancel loads for
* @return True iff Glide had ever been asked to load an image for this target
*/
public static boolean cancel(Target target) {
ImagePresenter current = target.getImagePresenter();
final boolean cancelled = current != null;
if (cancelled) {
current.clear();
}
return result;
}
private ImageViewTarget getImageViewTargetOrSet(ImageView imageView) {
ImageViewTarget result = getImageViewTarget(imageView);
if (result == null) {
result = new ImageViewTarget(imageView);
imageView.setTag(result);
}
return result;
return cancelled;
}
/**
* Set the {@link ModelLoader} to use for for a new load where the model loader translates from a model to an
* {@link InputStream} resource for loading images.
* Begin a load with Glide by passing in a context.
*
* @param modelLoader The model loader to use.
* @param <T> The type of the model.
* @return A new {@link ImageModelRequest}.
* @param context Any context, will not be retained.
* @return A model request to pass in the object representing the image to be loaded.
*/
public static <T> ImageModelRequest<T> using(final StreamModelLoader<T> modelLoader) {
return new ImageModelRequest<T>(modelLoaderToFactory(modelLoader));
public static ModelRequest with(Context context) {
return new ModelRequest(context);
}
/**
* Set the {@link ModelLoader} to use for a new load where the model loader translates from a model to an
* {@link ParcelFileDescriptor} resource for loading video thumbnails.
*
* @param modelLoader The model loader to use.
* @param <T> The type of the model.
* @return A new {@link VideoModelRequest}.
* A {@link Request} builder that returns a request for a model that represents an image.
*/
public static <T> VideoModelRequest<T> using(final FileDescriptorModelLoader<T> modelLoader) {
return new VideoModelRequest<T>(modelLoaderToFactory(modelLoader));
public static class ModelRequest {
private final Context context;
}
private ModelRequest(Context context) {
this.context = context;
}
/**
* Use the {@link ModelLoaderFactory} currently registered for {@link String} to load the image represented by the
* given {@link String}. Defaults to {@link StreamStringLoader.Factory} and {@link StreamStringLoader} to load the given model.
*
* @see #using(StreamModelLoader)
*
* @param string The string representing the image. Must be either a path, or a uri handled by {@link StreamUriLoader}
* @return A {@link GenericRequest} to set options for the load and ultimately the target to load the model into
*/
public static Request<String> load(String string) {
return new Request<String>(string);
}
/**
* Set the {@link ModelLoader} to use for for a new load where the model loader translates from a model to an
* {@link InputStream} resource for loading images.
*
* @param modelLoader The model loader to use.
* @param <T> The type of the model.
* @return A new {@link ImageModelRequest}.
*/
public <T> ImageModelRequest<T> using(final StreamModelLoader<T> modelLoader) {
return new ImageModelRequest<T>(context, modelLoaderToFactory(modelLoader));
}
/**
* Use the {@link ModelLoaderFactory} currently registered for {@link Uri} to load the image at the given uri.
* Defaults to {@link StreamUriLoader.Factory} and {@link StreamUriLoader}.
*
* @see #using(StreamModelLoader)
*
* @param uri The uri representing the image. Must be a uri handled by {@link StreamUriLoader}
* @return A {@link GenericRequest} to set options for the load and ultimately the target to load the model into
*/
public static Request<Uri> load(Uri uri) {
return new Request<Uri>(uri);
}
/**
* Set the {@link ModelLoader} to use for a new load where the model loader translates from a model to an
* {@link ParcelFileDescriptor} resource for loading video thumbnails.
*
* @param modelLoader The model loader to use.
* @param <T> The type of the model.
* @return A new {@link VideoModelRequest}.
*/
public <T> VideoModelRequest<T> using(final FileDescriptorModelLoader<T> modelLoader) {
return new VideoModelRequest<T>(context, modelLoaderToFactory(modelLoader));
/**
* Use the {@link ModelLoaderFactory} currently registered for {@link URL} to load the image represented by the
* given {@link URL}. Defaults to {@link VolleyUrlLoader.Factory} and {@link VolleyUrlLoader} to load the given
* model.
*
* @see #using(StreamModelLoader)
*
* @param url The URL representing the image.
* @return A {@link GenericRequest} to set options for the load and ultimately the target to load the model into
*/
public static Request<URL> load(URL url) {
return new Request<URL>(url);
}
}
/**
* Use the {@link ModelLoaderFactory} currently registered for {@link File} to load the image represented by the
* given {@link File}. Defaults to {@link StreamFileLoader.Factory} and {@link StreamFileLoader} to load the given model.
*
* @see #using(StreamModelLoader)
*
* @param file The File containing the image
* @return A {@link GenericRequest} to set options for the load and ultimately the target to load the model into
*/
public static Request<File> load(File file) {
return new Request<File>(file);
}
/**
* Use the {@link ModelLoaderFactory} currently registered for {@link String} to load the image represented by the
* given {@link String}. Defaults to {@link StreamStringLoader.Factory} and {@link StreamStringLoader} to load the given model.
*
* @see #using(StreamModelLoader)
*
* @param string The string representing the image. Must be either a path, or a uri handled by {@link StreamUriLoader}
* @return A {@link GenericRequest} to set options for the load and ultimately the target to load the model into
*/
public Request<String> load(String string) {
return new Request<String>(context, string);
}
/**
* Use the {@link ModelLoaderFactory} currently registered for {@link Integer} to load the image represented by the
* given {@link Integer} resource id. Defaults to {@link StreamResourceLoader.Factory} and {@link StreamResourceLoader} to load
* the given model.
*
* @see #using(StreamModelLoader)
*
* @param resourceId the id of the resource containing the image
* @return A {@link GenericRequest} to set options for the load and ultimately the target to load the model into
*/
public static Request<Integer> load(Integer resourceId) {
return new Request<Integer>(resourceId);
}
/**
* Use the {@link ModelLoaderFactory} currently registered for {@link Uri} to load the image at the given uri.
* Defaults to {@link StreamUriLoader.Factory} and {@link StreamUriLoader}.
*
* @see #using(StreamModelLoader)
*
* @param uri The uri representing the image. Must be a uri handled by {@link StreamUriLoader}
* @return A {@link GenericRequest} to set options for the load and ultimately the target to load the model into
*/
public Request<Uri> load(Uri uri) {
return new Request<Uri>(context, uri);
}
/**
* Use the {@link ModelLoaderFactory} currently registered for the given model type to load the image represented by
* the given model.
*
* @param model The model to load.
* @param <T> The type of the model to load.
* @return A {@link GenericRequest} to set options for the load and ultimately the target to load the image into.
* @throws IllegalArgumentException If no such {@link ModelLoaderFactory} is registered for the given model type.
*/
@SuppressWarnings("unused")
public static <T> Request<T> loadFromImage(T model) {
return new ImageModelRequest<T>(GLIDE.getFactory(model, InputStream.class)).load(model);
}
/**
* Use the {@link ModelLoaderFactory} currently registered for {@link URL} to load the image represented by the
* given {@link URL}. Defaults to {@link VolleyUrlLoader.Factory} and {@link VolleyUrlLoader} to load the given
* model.
*
* @see #using(StreamModelLoader)
*
* @param url The URL representing the image.
* @return A {@link GenericRequest} to set options for the load and ultimately the target to load the model into
*/
public Request<URL> load(URL url) {
return new Request<URL>(context, url);
}
/**
* Use the {@link ModelLoaderFactory} currently registered for the given model type for
* {@link ParcelFileDescriptor}s to load a thumbnail for the video represented by the given model.
*
* @param model The model to load.
* @param <T> The type of the model to load.
* @return A {@link Request} to set options for the load an ultimately the target to load the thumbnail into.
* @throws IllegalArgumentException If no such {@link ModelLoaderFactory} is registered for the given model type.
*/
@SuppressWarnings("unused")
public static <T> Request<T> loadFromVideo(T model) {
return new VideoModelRequest<T>(GLIDE.getFactory(model, ParcelFileDescriptor.class)).loadFromVideo(model);
}
/**
* Use the {@link ModelLoaderFactory} currently registered for {@link File} to load the image represented by the
* given {@link File}. Defaults to {@link StreamFileLoader.Factory} and {@link StreamFileLoader} to load the given model.
*
* @see #using(StreamModelLoader)
*
* @param file The File containing the image
* @return A {@link GenericRequest} to set options for the load and ultimately the target to load the model into
*/
public Request<File> load(File file) {
return new Request<File>(context, file);
}
/**
* @see #cancel(com.bumptech.glide.presenter.target.Target)
*/
public static boolean cancel(ImageView imageView) {
final Target target = GLIDE.getImageViewTarget(imageView);
return target != null && cancel(target);
}
/**
* Use the {@link ModelLoaderFactory} currently registered for {@link Integer} to load the image represented by the
* given {@link Integer} resource id. Defaults to {@link StreamResourceLoader.Factory} and {@link StreamResourceLoader} to load
* the given model.
*
* @see #using(StreamModelLoader)
*
* @param resourceId the id of the resource containing the image
* @return A {@link GenericRequest} to set options for the load and ultimately the target to load the model into
*/
public Request<Integer> load(Integer resourceId) {
return new Request<Integer>(context, resourceId);
}
/**
* Cancel any pending loads Glide may have for the target. After the load is cancelled Glide will not load
* a placeholder or bitmap into the target so it is safe to do so yourself until you start another load.
*
* @param target The Target to cancel loads for
* @return True iff Glide had ever been asked to load an image for this target
*/
public static boolean cancel(Target target) {
ImagePresenter current = target.getImagePresenter();
final boolean cancelled = current != null;
if (cancelled) {
current.clear();
/**
* Use the {@link ModelLoaderFactory} currently registered for the given model type to load the image represented by
* the given model.
*
* @param model The model to load.
* @param <T> The type of the model to load.
* @return A {@link GenericRequest} to set options for the load and ultimately the target to load the image into.
* @throws IllegalArgumentException If no such {@link ModelLoaderFactory} is registered for the given model type.
*/
@SuppressWarnings("unused")
public <T> Request<T> loadFromImage(T model) {
return new ImageModelRequest<T>(context, GLIDE.getFactory(model, InputStream.class)).load(model);
}
return cancelled;
/**
* Use the {@link ModelLoaderFactory} currently registered for the given model type for
* {@link ParcelFileDescriptor}s to load a thumbnail for the video represented by the given model.
*
* @param model The model to load.
* @param <T> The type of the model to load.
* @return A {@link Request} to set options for the load an ultimately the target to load the thumbnail into.
* @throws IllegalArgumentException If no such {@link ModelLoaderFactory} is registered for the given model type.
*/
@SuppressWarnings("unused")
public <T> Request<T> loadFromVideo(T model) {
return new VideoModelRequest<T>(context, GLIDE.getFactory(model, ParcelFileDescriptor.class))
.loadFromVideo(model);
}
}
/**
......@@ -414,14 +408,16 @@ public class Glide {
* @param <T> The type of the model.
*/
public static class VideoModelRequest<T> {
private final Context context;
private ModelLoaderFactory<T, ParcelFileDescriptor> factory;
private VideoModelRequest(ModelLoaderFactory<T, ParcelFileDescriptor> factory) {
private VideoModelRequest(Context context, ModelLoaderFactory<T, ParcelFileDescriptor> factory) {
this.context = context;
this.factory = factory;
}
public Request<T> loadFromVideo(T model) {
return new Request<T>(model, null, factory);
return new Request<T>(context, model, null, factory);
}
}
......@@ -433,36 +429,15 @@ public class Glide {
*/
public static class ImageModelRequest<T> {
private final ModelLoaderFactory<T, InputStream> factory;
private final Context context;
private ImageModelRequest(ModelLoaderFactory<T, InputStream> factory) {
private ImageModelRequest(Context context, ModelLoaderFactory<T, InputStream> factory) {
this.context = context;
this.factory = factory;
}
public Request<T> load(T model) {
return new Request<T>(model, factory, null);
}
}
/**
* An request for the user to provide an {@link Context} to start an image load.
*/
public static class ContextRequest {
private final GenericRequest request;
private final Target target;
private ContextRequest(GenericRequest request, Target target) {
this.request = request;
this.target = target;
}
/**
* Start loading the image using the given context. The context will not be referenced statically so any
* context is acceptable.
*
* @param context The context to use to help load the image.
*/
public void with(Context context) {
request.finish(context, target);
return new Request<T>(context, model, factory, null);
}
}
......@@ -474,15 +449,15 @@ public class Glide {
*/
@SuppressWarnings("unused") //public api
public static class Request<ModelType> extends GenericRequest<ModelType, InputStream, ParcelFileDescriptor> {
private Request(ModelType model) {
this(model, GLIDE.getFactory(model, InputStream.class),
private Request(Context context, ModelType model) {
this(context, model, GLIDE.getFactory(model, InputStream.class),
GLIDE.getFactory(model, ParcelFileDescriptor.class));
}
private Request(ModelType model,
private Request(Context context, ModelType model,
ModelLoaderFactory<ModelType, InputStream> imageFactory,
ModelLoaderFactory<ModelType, ParcelFileDescriptor> videoFactory) {
super(model, imageFactory, videoFactory);
super(context, model, imageFactory, videoFactory);
approximate().videoDecoder(new VideoBitmapDecoder());
}
......@@ -610,15 +585,20 @@ public class Glide {
private BitmapDecoder<ImageResourceType> imageDecoder;
private BitmapDecoder<VideoResourceType> videoDecoder;
private GenericRequest(ModelType model, ModelLoaderFactory<ModelType, ImageResourceType> imageFactory,
private GenericRequest(Context context, ModelType model, ModelLoaderFactory<ModelType, ImageResourceType> imageFactory,
ModelLoaderFactory<ModelType, VideoResourceType> videoFactory) {
if (model == null ) {
throw new IllegalArgumentException("Model can't be null");
if (context == null) {
throw new NullPointerException("Context can't be nul");
}
this.context = context;
if (model == null ) {
throw new NullPointerException("Model can't be null");
}
this.model = model;
if (imageFactory == null && videoFactory == null) {
throw new IllegalArgumentException("No ModelLoaderFactorys registered for either image or video type,"
throw new NullPointerException("No ModelLoaderFactorys registered for either image or video type,"
+ " class=" + model.getClass());
}
this.imageModelLoaderFactory = imageFactory;
......@@ -774,50 +754,25 @@ public class Glide {
return this;
}
/**
* Start loading the image into the view.
*
* <p>
* Note - This method will call {@link ImageView#setTag(Object)} and may silently overwrite any tag that
* might already be set on the view.
* </p>
*
* @see ImagePresenter#setModel(Object)
* @param imageView The view that will display the image
*/
public void into(ImageView imageView) {
finish(imageView.getContext(), GLIDE.getImageViewTargetOrSet(imageView));
}
/**
* Set the target the image will be loaded into.
*
* <p>
* Note - This method does not actually start loading the view. You must first pass in a {@link Context} to
* returned Request via {@link ContextRequest#with(android.content.Context)}.
* </p>
*
* @param target The target to load te image for
* @return A {@link ContextRequest} that can start the load
*/
public ContextRequest into(Target target) {
return new ContextRequest(this, target);
public <Y extends Target> Y into(Y target) {
return finish(target);
}
private void finish(Context context, Target target) {
this.context = context;
ImagePresenter<ModelType> imagePresenter = getImagePresenter(target);
private <Y extends Target> Y finish(Y target) {
ImagePresenter<ModelType, Y> imagePresenter = getImagePresenter(target);
imagePresenter.setModel(model);
return target;
}
/**
* Creates the new {@link ImagePresenter} if one does not currently exist for the current target and sets it as
* the target's ImagePresenter via {@link Target#setImagePresenter(com.bumptech.glide.presenter.ImagePresenter)}
*/
@SuppressWarnings("unchecked")
private ImagePresenter<ModelType> getImagePresenter(Target target) {
ImagePresenter<ModelType> result = target.getImagePresenter();
private <Y extends Target> ImagePresenter<ModelType, Y> getImagePresenter(Y target) {
ImagePresenter<ModelType, Y> result = target.getImagePresenter();
Metadata previous = GLIDE.metadataTracker.get(target);
Metadata current = new Metadata(this);
......@@ -832,7 +787,6 @@ public class Glide {
}
result = buildImagePresenter(target);
target.setImagePresenter(result);
GLIDE.metadataTracker.put(target, current);
}
......@@ -840,7 +794,7 @@ public class Glide {
return result;
}
private ImagePresenter<ModelType> buildImagePresenter(final Target target) {
private <Y extends Target> ImagePresenter<ModelType, Y> buildImagePresenter(final Y target) {
TransformationLoader<ModelType> transformationLoader = getFinalTransformationLoader();
ModelLoader<ModelType, ImageResourceType> imageModelLoader = null;
......@@ -852,7 +806,7 @@ public class Glide {
videoModelLoader = videoModelLoaderFactory.build(context, GLIDE.loaderFactory);
}
ImagePresenter.Builder<ModelType> builder = new ImagePresenter.Builder<ModelType>()
ImagePresenter.Builder<ModelType, Y> builder = new ImagePresenter.Builder<ModelType, Y>()
.setTarget(target, context)
.setBitmapLoadFactory(new BaseBitmapLoadFactory<ModelType, ImageResourceType, VideoResourceType>(
imageModelLoader, imageDecoder, videoModelLoader, videoDecoder, transformationLoader))
......@@ -865,9 +819,9 @@ public class Glide {
} else {
animation = null;
}
builder.setImageReadyCallback(new ImagePresenter.ImageReadyCallback<ModelType>() {
builder.setImageReadyCallback(new ImagePresenter.ImageReadyCallback<ModelType, Y>() {
@Override
public void onImageReady(ModelType model, Target target, boolean fromCache) {
public void onImageReady(ModelType model, Y target, boolean fromCache) {
if (animation != null && !fromCache) {
target.startAnimation(animation);
}
......@@ -927,7 +881,6 @@ public class Glide {
}
}
private static <T, Y> ModelLoaderFactory<T, Y> modelLoaderToFactory(final ModelLoader<T, Y> modelLoader) {
return new ModelLoaderFactory<T, Y>() {
@Override
......
......@@ -26,7 +26,6 @@ import java.util.Queue;
*/
public abstract class ListPreloader<T> implements AbsListView.OnScrollListener {
private final int maxPreload;
private final Context context;
private final PreloadTargetQueue preloadTargetQueue;
private int lastEnd;
......@@ -39,11 +38,9 @@ public abstract class ListPreloader<T> implements AbsListView.OnScrollListener {
/**
* Constructor for the preloader.
*
* @param context A context
* @param maxPreload The maximum number of items in the list to load ahead (corresponds to adapter positions).
*/
public ListPreloader(Context context, int maxPreload) {
this.context = context;
public ListPreloader(int maxPreload) {
this.maxPreload = maxPreload;
preloadTargetQueue = new PreloadTargetQueue(maxPreload);
}
......@@ -134,7 +131,7 @@ public abstract class ListPreloader<T> implements AbsListView.OnScrollListener {
final T item = items.get(position);
final int[] dimensions = getDimensions(item);
if (dimensions != null) {
getRequest(item).into(preloadTargetQueue.next(dimensions[0], dimensions[1])).with(context);
getRequest(item).into(preloadTargetQueue.next(dimensions[0], dimensions[1]));
}
}
......
......@@ -9,13 +9,13 @@ import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.widget.ImageView;
import com.bumptech.glide.loader.bitmap.BitmapLoadFactory;
import com.bumptech.glide.loader.bitmap.transformation.TransformationLoader;
import com.bumptech.glide.loader.image.ImageLoader;
import com.bumptech.glide.loader.bitmap.model.ModelLoader;
import com.bumptech.glide.presenter.target.ImageViewTarget;
import com.bumptech.glide.presenter.target.Target;
import com.bumptech.glide.resize.BitmapLoadTask;
import com.bumptech.glide.resize.load.Transformation;
/**
* Wraps an {@link Target} to display arbitrary Bitmaps and provides a framework for fetching and
......@@ -28,9 +28,8 @@ import com.bumptech.glide.resize.BitmapLoadTask;
* @param <T> The type of the model that contains information necessary to display an image. Can be as simple
* as a String containing a path or a complex data type.
*/
public class ImagePresenter<T> {
public class ImagePresenter<T, Y extends Target> {
private static final String TAG = "ImagePresenter";
private final BitmapLoadFactory<T> loadFactory;
/**
* A builder for an {@link ImagePresenter}.
......@@ -43,10 +42,10 @@ public class ImagePresenter<T> {
* @param <T> The type of the model that the presenter this builder will produce requires to load an image.
*/
@SuppressWarnings("unused")
public static class Builder<T> {
public static class Builder<T, Y extends Target> {
private int placeholderResourceId;
private Drawable placeholderDrawable;
private ImageReadyCallback<T> imageReadyCallback;
private ImageReadyCallback<T, Y> imageReadyCallback;
private ImagePresenterCoordinator coordinator;
private ImageLoader imageLoader;
private Context context;
......@@ -61,15 +60,16 @@ public class ImagePresenter<T> {
private int errorResourceId;
private Drawable errorDrawable;
private Target target;
BitmapLoadFactory<T> loadFactory;
private BitmapLoadFactory<T> loadFactory;
private TransformationLoader<T> transformationLoader;
private Y target;
/**
* Builds an ImagePresenter.
*
* @return A new ImagePresenter
*/
public ImagePresenter<T> build(){
public ImagePresenter<T, Y> build(){
if (target == null) {
throw new IllegalArgumentException("cannot create presenter without a target");
}
......@@ -80,36 +80,17 @@ public class ImagePresenter<T> {
throw new IllegalArgumentException("cannot create presenter without a bitmap load factory");
}
return new ImagePresenter<T>(this);
return new ImagePresenter<T, Y>(this);
}
/**
* Required - Sets the {@link android.widget.ImageView} the presenter will use to display any loaded bitmaps.
* Alternatively you can instead set a more general target for an object other than an ImageView using
* {@link #setTarget(com.bumptech.glide.presenter.target.Target, android.content.Context)}.
*
* @see #setTarget(Target, Context)
*
* @param imageView The {@link android.widget.ImageView} to wrap
* @return This Builder object
*/
public Builder<T> setImageView(final ImageView imageView) {
setTarget(new ImageViewTarget(imageView), imageView.getContext());
return this;
}
/**
* Required - Sets the {@link Target} the presenter will use to display any loaded bitmaps. If you are loading
* bitmaps into an {@link ImageView}, you can instead use {@link #setImageView(android.widget.ImageView)}.
*
* @see #setImageView(ImageView)
* Required - Sets the {@link Target} the presenter will use to display any loaded bitmaps.
*
* @param target The {@link Target} to wrap
* @param context A context that can be held for the duration of the load
* @return This builder object
*/
public Builder<T> setTarget(Target target, Context context) {
public Builder<T, Y> setTarget(Y target, Context context) {
this.target = target;
this.context = context;
......@@ -123,9 +104,8 @@ public class ImagePresenter<T> {
* @param loadFactory The {@link BitmapLoadFactory} to use to obtain the id and InputStreams
* @return This Builder object
*/
public Builder<T> setBitmapLoadFactory(BitmapLoadFactory<T> loadFactory) {
public Builder<T, Y> setBitmapLoadFactory(BitmapLoadFactory<T> loadFactory) {
this.loadFactory = loadFactory;
return this;
}
......@@ -136,7 +116,7 @@ public class ImagePresenter<T> {
* @param imageLoader The {@link com.bumptech.glide.loader.image.ImageLoader} to use to load an image
* @return This Builder object
*/
public Builder<T> setImageLoader(ImageLoader imageLoader) {
public Builder<T, Y> setImageLoader(ImageLoader imageLoader) {
this.imageLoader = imageLoader;
return this;
}
......@@ -149,7 +129,7 @@ public class ImagePresenter<T> {
* @param resourceId The id of the resource to show
* @return This Builder object
*/
public Builder<T> setPlaceholderResource(int resourceId) {
public Builder<T, Y> setPlaceholderResource(int resourceId) {
if (resourceId != 0 && placeholderDrawable != null) {
throw new IllegalArgumentException("Can't set both a placeholder drawable and a placeholder resource");
}
......@@ -166,7 +146,7 @@ public class ImagePresenter<T> {
* @param placeholderDrawable The drawable to show
* @return This Builder object
*/
public Builder<T> setPlaceholderDrawable(Drawable placeholderDrawable) {
public Builder<T, Y> setPlaceholderDrawable(Drawable placeholderDrawable) {
if (placeholderDrawable != null && placeholderResourceId != 0) {
throw new IllegalArgumentException("Can't set both a placeholder drawable and a placeholder resource");
}
......@@ -182,7 +162,7 @@ public class ImagePresenter<T> {
* @param resourceId The id of the resource to show
* @return This Builder object
*/
public Builder<T> setErrorResource(int resourceId) {
public Builder<T, Y> setErrorResource(int resourceId) {
if (resourceId != 0 && errorDrawable != null) {
throw new IllegalArgumentException("Can't set both an error drawable and an error resource");
}
......@@ -198,7 +178,7 @@ public class ImagePresenter<T> {
* @param drawable The drawable to show
* @return This Builder object
*/
public Builder<T> setErrorDrawable(Drawable drawable) {
public Builder<T, Y> setErrorDrawable(Drawable drawable) {
if (errorResourceId != 0 && drawable != null) {
throw new IllegalArgumentException("Can't set both an error drawable and an error resource");
}
......@@ -215,7 +195,7 @@ public class ImagePresenter<T> {
* @param cb The callback to call
* @return This Builder object
*/
public Builder<T> setImageReadyCallback(ImageReadyCallback<T> cb) {
public Builder<T, Y> setImageReadyCallback(ImageReadyCallback<T, Y> cb) {
this.imageReadyCallback = cb;
return this;
}
......@@ -229,7 +209,7 @@ public class ImagePresenter<T> {
* @param coordinator The coordinator to set
* @return This Builder object
*/
public Builder<T> setImagePresenterCoordinator(ImagePresenterCoordinator coordinator) {
public Builder<T, Y> setImagePresenterCoordinator(ImagePresenterCoordinator coordinator) {
this.coordinator = coordinator;
return this;
}
......@@ -242,21 +222,35 @@ public class ImagePresenter<T> {
* @param exceptionHandler The exception handler to set
* @return This builder object
*/
public Builder<T> setExceptionHandler(ExceptionHandler<T> exceptionHandler) {
public Builder<T, Y> setExceptionHandler(ExceptionHandler<T> exceptionHandler) {
this.exceptionHandler = exceptionHandler;
return this;
}
/**
* Optional - Sets a transformation loader to use to obtain a transformation to apply to images on a per
* model basis.
*
* @see Transformation
*
* @param transformationLoader A {@link TransformationLoader} for this model type
* @return This builder object
*/
public Builder<T, Y> setTransformationLoader(TransformationLoader<T> transformationLoader) {
this.transformationLoader = transformationLoader;
return this;
}
}
@SuppressWarnings("all")
private Object imageToken; //this is just a reference we may need to keep, otherwise unused
private final Target target;
private final Y target;
private final ImageLoader imageLoader;
private final Drawable placeholderDrawable;
private final ImageReadyCallback<T> imageReadyCallback;
private final ImageReadyCallback<T, Y> imageReadyCallback;
private final ImagePresenterCoordinator coordinator;
private final ExceptionHandler<T> exceptionHandler;
......@@ -266,6 +260,7 @@ public class ImagePresenter<T> {
private boolean isImageSet = false;
private boolean isErrorSet = false;
private final BitmapLoadFactory<T> loadFactory;
private boolean loadedFromCache = false;
private final Drawable errorDrawable;
......@@ -311,7 +306,7 @@ public class ImagePresenter<T> {
* 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> {
public interface ImageReadyCallback<T, Y extends Target> {
/**
* The method called when a bitmap is set
......@@ -319,10 +314,10 @@ public class ImagePresenter<T> {
* @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);
public void onImageReady(T model, Y target, boolean fromCache);
}
protected ImagePresenter(Builder<T> builder) {
protected ImagePresenter(Builder<T, Y> builder) {
this.imageLoader = builder.imageLoader;
final Resources res = builder.context.getResources();
......@@ -342,6 +337,11 @@ public class ImagePresenter<T> {
this.exceptionHandler = builder.exceptionHandler;
this.loadFactory = builder.loadFactory;
this.target = builder.target;
final ImagePresenter previous = builder.target.getImagePresenter();
if (previous != null) {
previous.clear();
}
builder.target.setImagePresenter(this);
}
/**
......
......@@ -4,8 +4,9 @@
package com.bumptech.glide.presenter;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.widget.ImageView;
import com.bumptech.glide.presenter.target.Target;
/**
*Wraps a pair of {@link ImagePresenter} objects and uses them to load and display an image and a thumbnail for that
......@@ -15,7 +16,7 @@ import android.widget.ImageView;
* shown until the image load completes. If the image load completes first, the thumbnail will never be shown.
*/
@SuppressWarnings("unused")
public class ThumbImagePresenter<A, B> implements ImagePresenter.ImagePresenterCoordinator {
public class ThumbImagePresenter<A, B, C extends Target> implements ImagePresenter.ImagePresenterCoordinator {
/**
* A builder for a {@link ThumbImagePresenter}. Has a few convenience methods to avoid identical calls on both
......@@ -26,25 +27,26 @@ public class ThumbImagePresenter<A, B> implements ImagePresenter.ImagePresenterC
* @param <A> The type of the model that the full {@link ImagePresenter} requires
* @param <B> The type of the model that the thumb {@link ImagePresenter} requires
*/
public static class Builder<A, B> {
private ImagePresenter.Builder<A> fullPresenterBuilder;
private ImagePresenter.Builder<B> thumbPresenterBuilder;
private ImageView imageView;
public static class Builder<A, B, C extends Target> {
private ImagePresenter.Builder<A, C> fullPresenterBuilder;
private ImagePresenter.Builder<B, C> thumbPresenterBuilder;
private Drawable placeholderDrawable;
private int placeholderResourceId;
private Context context;
private C target;
public ThumbImagePresenter<A, B> build(){
public ThumbImagePresenter<A, B, C> build(){
if (fullPresenterBuilder == null) {
throw new IllegalArgumentException("you must include a builder for the full image presenter");
}
if (thumbPresenterBuilder == null) {
throw new IllegalArgumentException("you must include a builder for the thumb image presenter");
}
if (imageView == null){
if (target == null){
throw new IllegalArgumentException("cannot create presenter without an image view");
}
return new ThumbImagePresenter<A, B>(this);
return new ThumbImagePresenter<A, B, C>(this);
}
/**
......@@ -54,7 +56,7 @@ public class ThumbImagePresenter<A, B> implements ImagePresenter.ImagePresenterC
* and {@link ImagePresenter.Builder ImagePresenter.Builder#setImageLoader} must have been called
* @return This builder object
*/
public Builder<A, B> setFullPresenterBuilder(ImagePresenter.Builder<A> builder) {
public Builder<A, B, C> setFullPresenterBuilder(ImagePresenter.Builder<A, C> builder) {
this.fullPresenterBuilder = builder;
return this;
}
......@@ -66,7 +68,7 @@ public class ThumbImagePresenter<A, B> implements ImagePresenter.ImagePresenterC
* and {@link ImagePresenter.Builder ImagePresenter.Builder#setImageLoader} must have been called
* @return This builder object
*/
public Builder<A, B> setThumbPresenterBuilder(ImagePresenter.Builder<B> builder) {
public Builder<A, B, C> setThumbPresenterBuilder(ImagePresenter.Builder<B, C> builder) {
this.thumbPresenterBuilder = builder;
return this;
}
......@@ -74,15 +76,16 @@ public class ThumbImagePresenter<A, B> implements ImagePresenter.ImagePresenterC
/**
* @see ImagePresenter.Builder ImagePresenter.Builder#setImageView
*/
public Builder<A, B> setImageView(ImageView imageView) {
this.imageView = imageView;
public Builder<A, B, C> setTarget(C target, Context context) {
this.target = target;
this.context = context;
return this;
}
/**
* @see ImagePresenter.Builder ImagePresenter.Builder#setPlaceholderDrawable
*/
public Builder<A, B> setPlaceholderDrawable(Drawable drawable) {
public Builder<A, B, C> setPlaceholderDrawable(Drawable drawable) {
if (drawable != null && this.placeholderResourceId != 0) {
throw new IllegalArgumentException("Can't set both a placeholder drawable and a placeholder resource");
}
......@@ -94,7 +97,7 @@ public class ThumbImagePresenter<A, B> implements ImagePresenter.ImagePresenterC
/**
* @see ImagePresenter.Builder ImagePresenter.Builder#setPlaceholderResource
*/
public Builder<A, B> setPlaceholderResource(int resourceId) {
public Builder<A, B, C> setPlaceholderResource(int resourceId) {
if (resourceId != 0 && placeholderDrawable != null) {
throw new IllegalArgumentException("Can't set both a placeholder drawable and a placeholder resource");
}
......@@ -104,20 +107,21 @@ public class ThumbImagePresenter<A, B> implements ImagePresenter.ImagePresenterC
}
}
private final ImagePresenter<A> fullPresenter;
private final ImagePresenter<B> thumbPresenter;
private final ImagePresenter<A, C> fullPresenter;
private final ImagePresenter<B, C> thumbPresenter;
private ThumbImagePresenter(Builder<A, B> builder) {
private ThumbImagePresenter(Builder<A, B, C> builder) {
fullPresenter = builder.fullPresenterBuilder
.setImagePresenterCoordinator(this)
.setImageView(builder.imageView)
.setTarget(builder.target, builder.context)
.setPlaceholderResource(0)
.setPlaceholderDrawable(builder.placeholderDrawable == null ?
builder.imageView.getResources().getDrawable(builder.placeholderResourceId) : builder.placeholderDrawable)
builder.context.getResources().getDrawable(builder.placeholderResourceId)
: builder.placeholderDrawable)
.build();
thumbPresenter = builder.thumbPresenterBuilder
.setImagePresenterCoordinator(this)
.setImageView(builder.imageView)
.setTarget(builder.target, builder.context)
.setPlaceholderDrawable(null)
.setPlaceholderResource(0)
.build();
......
package com.bumptech.glide.presenter.target;
import com.bumptech.glide.presenter.ImagePresenter;
public abstract class BaseTarget implements Target {
private ImagePresenter imagePresenter;
@Override
public void setImagePresenter(ImagePresenter imagePresenter) {
this.imagePresenter = imagePresenter;
}
@Override
public ImagePresenter getImagePresenter() {
return imagePresenter;
}
}
......@@ -10,7 +10,6 @@ import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.widget.ImageView;
import com.bumptech.glide.presenter.ImagePresenter;
import java.lang.ref.WeakReference;
......@@ -19,17 +18,20 @@ import static android.view.ViewGroup.LayoutParams;
/**
* A target wrapping an ImageView. Obtains the runtime dimensions of the ImageView.
*/
public class ImageViewTarget implements Target {
public class ImageViewTarget extends BaseTarget {
private static final String TAG = "ImageViewTarget";
private final ImageView imageView;
private final SizeDeterminer sizeDeterminer;
private ImagePresenter imagePresenter;
public ImageViewTarget(ImageView imageView) {
this.imageView = imageView;
this.sizeDeterminer = new SizeDeterminer(imageView);
}
public ImageView getView() {
return imageView;
}
@Override
public void onImageReady(Bitmap bitmap) {
imageView.setImageBitmap(bitmap);
......@@ -52,16 +54,6 @@ public class ImageViewTarget implements Target {
imageView.startAnimation(animation);
}
@Override
public void setImagePresenter(ImagePresenter imagePresenter) {
this.imagePresenter = imagePresenter;
}
@Override
public ImagePresenter getImagePresenter() {
return imagePresenter;
}
@Override
public int hashCode() {
return imageView.hashCode();
......
......@@ -7,8 +7,7 @@ import com.bumptech.glide.presenter.ImagePresenter;
/**
* A simpler interface for targets with default (usually noop) implementations of non essential methods.
*/
public abstract class SimpleTarget implements Target {
private ImagePresenter imagePresenter;
public abstract class SimpleTarget extends BaseTarget {
@Override
public void setPlaceholder(Drawable placeholder) { }
......@@ -16,16 +15,6 @@ public abstract class SimpleTarget implements Target {
@Override
public void startAnimation(Animation animation) { }
@Override
public void setImagePresenter(ImagePresenter imagePresenter) {
this.imagePresenter = imagePresenter;
}
@Override
public ImagePresenter getImagePresenter() {
return imagePresenter;
}
/**
* A default implementation that calls {@link com.bumptech.glide.presenter.target.Target.SizeReadyCallback}
* synchronously with {@link #getSize()}
......
......@@ -46,19 +46,7 @@ public interface Target {
*/
public void startAnimation(Animation animation);
/**
* A method that is used to keep a reference to the ImagePresenter. Increases the efficiency of loads if it is
* possible that this target object will be used more than once.
*
* @param imagePresenter The ImagePresenter to store
*/
public void setImagePresenter(ImagePresenter imagePresenter);
/**
* A method for retrieving any current ImagePresenter. Increases the efficiency of loads if it is possible that this
* target object will be used more than once.
*
* @return The current ImagePresenter or null
*/
public ImagePresenter getImagePresenter();
}
package com.bumptech.glide;
import android.content.Context;
import android.graphics.Bitmap;
import android.net.Uri;
import android.test.ActivityTestCase;
......@@ -23,17 +24,23 @@ import java.net.URL;
*/
public class GlideTest extends ActivityTestCase {
private ImageView imageView;
private ImageViewTarget imageViewTarget;
@Override
protected void setUp() throws Exception {
super.setUp();
imageView = new ImageView(getInstrumentation().getContext());
imageView = new ImageView(getContext());
//this is a quick hack to get the SizeDeterminer in ImagePresenter to think the view has been measured
imageView.setLayoutParams(new ViewGroup.LayoutParams(100, 100));
imageViewTarget = new ImageViewTarget(imageView);
}
private void checkImagePresenter(Object model) {
ImagePresenter imagePresenter = getImagePresenterFromView();
private Context getContext() {
return getInstrumentation().getContext();
}
private void checkImagePresenter(Target target, Object model) {
ImagePresenter imagePresenter = target.getImagePresenter();
imagePresenter.setModel(model);
boolean caughtException = false;
......@@ -46,58 +53,56 @@ public class GlideTest extends ActivityTestCase {
assertTrue(caughtException);
}
private ImagePresenter getImagePresenterFromView() {
return ((ImageViewTarget) imageView.getTag()).getImagePresenter();
}
public void testFileDefaultLoader() {
File file = new File("fake");
Glide.load(file).into(imageView);
checkImagePresenter(file);
Target target = Glide.with(getContext()).load(file).into(imageViewTarget);
checkImagePresenter(target, file);
}
public void testUrlDefaultLoader() throws MalformedURLException {
URL url = new URL("http://www.google.com");
Glide.load(url).into(imageView);
checkImagePresenter(url);
Target target = Glide.with(getContext()).load(url).into(imageViewTarget);
checkImagePresenter(target, url);
}
public void testUriDefaultLoader() {
Uri uri = Uri.fromFile(new File("Fake"));
Glide.load(uri).into(imageView);
checkImagePresenter(uri);
Target target = Glide.with(getContext()).load(uri).into(imageViewTarget);
checkImagePresenter(target, uri);
}
public void testStringDefaultLoader() {
String string = "http://www.google.com";
Glide.load(string).into(imageView);
checkImagePresenter(string);
Target target = Glide.with(getContext()).load(string).into(imageViewTarget);
checkImagePresenter(target, string);
}
public void testIntegerDefaultLoader() {
int integer = 1234;
Glide.load(integer).into(imageView);
checkImagePresenter(integer);
Target target = Glide.with(getContext()).load(integer).into(imageViewTarget);
checkImagePresenter(target, integer);
}
public void testGlideDoesNotReplaceIdenticalPresenters() {
Glide.load("fake")
Target target = Glide.with(getContext())
.load("fake")
.asIs()
.centerCrop()
.animate(android.R.anim.fade_in)
.placeholder(com.bumptech.glide.tests.R.raw.ic_launcher)
.error(com.bumptech.glide.tests.R.raw.ic_launcher)
.into(imageView);
ImagePresenter first = getImagePresenterFromView();
.into(imageViewTarget);
ImagePresenter first = target.getImagePresenter();
Glide.load("fake2")
Target target2 = Glide.with(getContext())
.load("fake2")
.asIs()
.centerCrop()
.animate(android.R.anim.fade_in)
.placeholder(com.bumptech.glide.tests.R.raw.ic_launcher)
.error(com.bumptech.glide.tests.R.raw.ic_launcher)
.into(imageView);
ImagePresenter second = getImagePresenterFromView();
.into(imageViewTarget);
ImagePresenter second = target2.getImagePresenter();
assertSame(first, second);
}
......@@ -105,23 +110,23 @@ public class GlideTest extends ActivityTestCase {
public void testCanHandleWrapContent() {
imageView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
Glide.load("fake").into(imageView);
Target target = Glide.with(getContext()).load("fake").into(imageViewTarget);
assertNotNull(getImagePresenterFromView());
assertNotNull(target.getImagePresenter());
}
public void testCanHandleWrapContentMatchParent() {
imageView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.MATCH_PARENT));
Glide.load("fake").into(imageView);
Target target = Glide.with(getContext()).load("fake").into(imageViewTarget);
assertNotNull(getImagePresenterFromView());
assertNotNull(target.getImagePresenter());
}
public void testDifferentModelTypesReplacesPresenters() {
assertDifferentPresenters(
Glide.load(4),
Glide.load("fake")
Glide.with(getContext()).load(4),
Glide.with(getContext()).load("fake")
);
}
......@@ -182,31 +187,31 @@ public class GlideTest extends ActivityTestCase {
final Object object = new Object();
assertDifferentPresenters(
Glide.using(first).load(object),
Glide.using(second).load(object)
Glide.with(getContext()).using(first).load(object),
Glide.with(getContext()).using(second).load(object)
);
}
public void testDifferentDownsamplersReplacesPresenter() {
assertDifferentPresenters(
Glide.load("a").approximate(),
Glide.load("a").asIs()
Glide.with(getContext()).load("a").approximate(),
Glide.with(getContext()).load("a").asIs()
);
}
public void testDifferentTransformationsReplacesPresenter() {
final File file = new File("fake");
assertDifferentPresenters(
Glide.load(file).centerCrop().fitCenter(),
Glide.load(file).centerCrop()
Glide.with(getContext()).load(file).centerCrop().fitCenter(),
Glide.with(getContext()).load(file).centerCrop()
);
}
public void testDifferentPlaceholdersReplacesPresenter() {
final File file = new File("fake");
assertDifferentPresenters(
Glide.load(file).placeholder(com.bumptech.glide.tests.R.raw.ic_launcher),
Glide.load(file)
Glide.with(getContext()).load(file).placeholder(com.bumptech.glide.tests.R.raw.ic_launcher),
Glide.with(getContext()).load(file)
);
}
......@@ -214,25 +219,18 @@ public class GlideTest extends ActivityTestCase {
public void testDifferentAnimationsReplacesPresenter() {
final File file = new File("fake");
assertDifferentPresenters(
Glide.load(file).animate(android.R.anim.fade_in),
Glide.load(file).animate(android.R.anim.fade_out)
Glide.with(getContext()).load(file).animate(android.R.anim.fade_in),
Glide.with(getContext()).load(file).animate(android.R.anim.fade_out)
);
}
public void testDifferentErrorIdsReplacesPresenter() {
assertDifferentPresenters(
Glide.load("b").error(R.raw.ic_launcher),
Glide.load("b").error(android.R.drawable.btn_star)
Glide.with(getContext()).load("b").error(R.raw.ic_launcher),
Glide.with(getContext()).load("b").error(android.R.drawable.btn_star)
);
}
public void testClearingTagReplacesPresenter() {
Glide.load("a").into(imageView);
assertNotNull(imageView.getTag());
imageView.setTag(null);
Glide.load("b").into(imageView);
}
public void testObtainAndOfferToBitmapPool() {
Bitmap small = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
Bitmap large = Bitmap.createBitmap(512, 512, Bitmap.Config.RGB_565);
......@@ -244,21 +242,9 @@ public class GlideTest extends ActivityTestCase {
assertEquals(large, bitmapPool.get(large.getWidth(), large.getHeight(), large.getConfig()));
}
public void testThrowExceptionIfTagReplaced() {
imageView.setTag(1234);
Exception exception = null;
try {
Glide.load("a").into(imageView);
} catch (Exception e) {
exception = e;
}
assertNotNull(exception);
}
public void testDifferentRequestListenersReplacesPresenter() {
assertDifferentPresenters(
Glide.load("a").listener(new Glide.RequestListener<String>() {
Glide.with(getContext()).load("a").listener(new Glide.RequestListener<String>() {
@Override
public void onException(Exception e, String model, Target target) {
......@@ -269,7 +255,7 @@ public class GlideTest extends ActivityTestCase {
public void onImageReady(String model, Target target) {
}
}),
Glide.load("a").listener(new Glide.RequestListener<String>() {
Glide.with(getContext()).load("a").listener(new Glide.RequestListener<String>() {
@Override
public void onException(Exception e, String model, Target target) {
}
......@@ -350,14 +336,9 @@ public class GlideTest extends ActivityTestCase {
// }
private void assertDifferentPresenters(Glide.Request a, Glide.Request b) {
a.into(imageView);
ImagePresenter first = getImagePresenterFromView();
a.into(imageView);
ImagePresenter second = getImagePresenterFromView();
b.into(imageView);
ImagePresenter third = getImagePresenterFromView();
ImagePresenter first = a.into(imageViewTarget).getImagePresenter();
ImagePresenter second = a.into(imageViewTarget).getImagePresenter();
ImagePresenter third = b.into(imageViewTarget).getImagePresenter();
assertSame(first, second);
assertNotSame(first, third);
......
......@@ -11,6 +11,7 @@ import com.bumptech.glide.loader.bitmap.BitmapLoadFactory;
import com.bumptech.glide.loader.image.ImageLoader;
import com.bumptech.glide.loader.image.ImageManagerLoader;
import com.bumptech.glide.presenter.ImagePresenter;
import com.bumptech.glide.presenter.target.BaseTarget;
import com.bumptech.glide.presenter.target.Target;
import com.bumptech.glide.resize.BitmapLoadTask;
import com.bumptech.glide.resize.bitmap_recycle.BitmapPool;
......@@ -69,10 +70,8 @@ public class ImagePresenterTest extends AndroidTestCase {
public void testMustProvideATarget() {
Exception exception = null;
try {
new ImagePresenter.Builder<Object>()
new ImagePresenter.Builder<Object, Target>()
.setBitmapLoadFactory(new MockBitmapLoadFactory())
.setBitmapLoadFactory(new MockBitmapLoadFactory())
.setImageLoader(new MockImageLoader())
.build();
} catch (Exception e) {
exception = e;
......@@ -83,7 +82,7 @@ public class ImagePresenterTest extends AndroidTestCase {
public void testMustProvideAModelLoader() {
Exception exception = null;
try {
new ImagePresenter.Builder<Object>()
new ImagePresenter.Builder<Object, Target>()
.setTarget(target, getContext())
.setImageLoader(new MockImageLoader())
.build();
......@@ -96,7 +95,7 @@ public class ImagePresenterTest extends AndroidTestCase {
public void testMustProvideAnImageLoader() {
Exception exception = null;
try {
new ImagePresenter.Builder<Object>()
new ImagePresenter.Builder<Object, Target>()
.setTarget(target, getContext())
.setBitmapLoadFactory(new MockBitmapLoadFactory())
.build();
......@@ -108,7 +107,7 @@ public class ImagePresenterTest extends AndroidTestCase {
public void testPlaceholderIsSetWithNullModel() {
Drawable placeholder = new ColorDrawable(Color.RED);
ImagePresenter<Object> imagePresenter = new ImagePresenter.Builder<Object>()
ImagePresenter<Object, Target> imagePresenter = new ImagePresenter.Builder<Object, Target>()
.setTarget(target, getContext())
.setBitmapLoadFactory(new MockBitmapLoadFactory())
.setImageLoader(new ImageManagerLoader(getContext()))
......@@ -121,7 +120,7 @@ public class ImagePresenterTest extends AndroidTestCase {
public void testPlaceholderIsSetWithNullBitmapLoadTask() {
Drawable placeholder = new ColorDrawable(Color.RED);
final Bitmap result = Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8);
ImagePresenter<Object> imagePresenter = new ImagePresenter.Builder<Object>()
ImagePresenter<Object, Target> imagePresenter = new ImagePresenter.Builder<Object, Target>()
.setTarget(target, getContext())
.setBitmapLoadFactory(new MockBitmapLoadFactory() {
@Override
......@@ -144,7 +143,7 @@ public class ImagePresenterTest extends AndroidTestCase {
public void testPlaceholderIsSetDuringAsynchronousLoad() {
Drawable placeholder = new ColorDrawable(Color.RED);
ImagePresenter<Object> imagePresenter = new ImagePresenter.Builder<Object>()
ImagePresenter<Object, Target> imagePresenter = new ImagePresenter.Builder<Object, Target>()
.setTarget(target, getContext())
.setBitmapLoadFactory(new MockBitmapLoadFactory())
.setImageLoader(new MockImageLoader())
......@@ -160,7 +159,7 @@ public class ImagePresenterTest extends AndroidTestCase {
final Bitmap result = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_4444);
final AtomicBoolean wasPlaceholderEverSet = new AtomicBoolean(false);
ImagePresenter<Object> imagePresenter = new ImagePresenter.Builder<Object>()
ImagePresenter<Object, Target> imagePresenter = new ImagePresenter.Builder<Object, Target>()
.setTarget(new MockTarget() {
@Override
public void setPlaceholder(Drawable placeholder) {
......@@ -184,7 +183,7 @@ public class ImagePresenterTest extends AndroidTestCase {
public void testErrorPlaceholderIsSetOnException() {
Drawable errorDrawable = new ColorDrawable(Color.RED);
ImagePresenter<Object> imagePresenter = new ImagePresenter.Builder<Object>()
ImagePresenter<Object, Target> imagePresenter = new ImagePresenter.Builder<Object, Target>()
.setTarget(target, getContext())
.setBitmapLoadFactory(new MockBitmapLoadFactory())
.setImageLoader(new MockImageLoader().onCallback(new MockImageLoader.CallbackAction() {
......@@ -202,7 +201,7 @@ public class ImagePresenterTest extends AndroidTestCase {
public void testBitmapIsSetWhenLoaded() {
final Bitmap result = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
ImagePresenter<Object> imagePresenter = new ImagePresenter.Builder<Object>()
ImagePresenter<Object, Target> imagePresenter = new ImagePresenter.Builder<Object, Target>()
.setTarget(target, getContext())
.setBitmapLoadFactory(new MockBitmapLoadFactory())
.setImageLoader(new MockImageLoader().onCallback(new MockImageLoader.CallbackAction() {
......@@ -221,7 +220,7 @@ public class ImagePresenterTest extends AndroidTestCase {
final Bitmap second = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_4444);
final List<ImageLoader.ImageReadyCallback> cbs = new ArrayList<ImageLoader.ImageReadyCallback>();
ImagePresenter<Object> imagePresenter = new ImagePresenter.Builder<Object>()
ImagePresenter<Object, Target> imagePresenter = new ImagePresenter.Builder<Object, Target>()
.setTarget(target, getContext())
.setBitmapLoadFactory(new MockBitmapLoadFactory())
.setImageLoader(new MockImageLoader().onCallback(new MockImageLoader.CallbackAction() {
......@@ -245,7 +244,7 @@ public class ImagePresenterTest extends AndroidTestCase {
final Object actualModel = new Object();
final AtomicBoolean wasOnExceptionCalled = new AtomicBoolean(false);
ImagePresenter<Object> imagePresenter = new ImagePresenter.Builder<Object>()
ImagePresenter<Object, Target> imagePresenter = new ImagePresenter.Builder<Object, Target>()
.setTarget(target, getContext())
.setBitmapLoadFactory(new MockBitmapLoadFactory())
.setImageLoader(new MockImageLoader().onCallback(new MockImageLoader.CallbackAction() {
......@@ -273,7 +272,7 @@ public class ImagePresenterTest extends AndroidTestCase {
final Object model = new Object();
final AtomicInteger timesMockImageLoaderCalled = new AtomicInteger();
ImagePresenter<Object> imagePresenter = new ImagePresenter.Builder<Object>()
ImagePresenter<Object, Target> imagePresenter = new ImagePresenter.Builder<Object, Target>()
.setTarget(target, getContext())
.setBitmapLoadFactory(new MockBitmapLoadFactory())
.setImageLoader(new MockImageLoader().onCallback(new MockImageLoader.CallbackAction() {
......@@ -293,7 +292,7 @@ public class ImagePresenterTest extends AndroidTestCase {
public void testImageSetCallbackIsCalledWhenImageIsSet() {
final AtomicBoolean wasImageSetCallbackCalled = new AtomicBoolean(false);
ImagePresenter<Object> imagePresenter = new ImagePresenter.Builder<Object>()
ImagePresenter<Object, Target> imagePresenter = new ImagePresenter.Builder<Object, Target>()
.setTarget(target, getContext())
.setBitmapLoadFactory(new MockBitmapLoadFactory())
.setImageLoader(new MockImageLoader().onCallback(new MockImageLoader.CallbackAction() {
......@@ -302,7 +301,7 @@ public class ImagePresenterTest extends AndroidTestCase {
cb.onImageReady(Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_4444));
}
}))
.setImageReadyCallback(new ImagePresenter.ImageReadyCallback<Object>() {
.setImageReadyCallback(new ImagePresenter.ImageReadyCallback<Object, Target>() {
@Override
public void onImageReady(Object model, Target target, boolean fromCache) {
wasImageSetCallbackCalled.set(true);
......@@ -314,7 +313,7 @@ public class ImagePresenterTest extends AndroidTestCase {
assertTrue(wasImageSetCallbackCalled.get());
}
private static class MockTarget implements Target {
private static class MockTarget extends BaseTarget {
private Bitmap bitmap = null;
private Drawable placeholder = null;
......@@ -347,15 +346,6 @@ public class ImagePresenterTest extends AndroidTestCase {
@Override
public void startAnimation(Animation animation) {
}
@Override
public void setImagePresenter(ImagePresenter imagePresenter) {
}
@Override
public ImagePresenter getImagePresenter() {
return null;
}
}
private static class MockImageLoader implements ImageLoader {
......
......@@ -168,10 +168,12 @@ public class ListPreloaderTest extends AndroidTestCase {
}
private static class ListPreloaderAdapter extends ListPreloader<Object> {
private final Context context;
public Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
public ListPreloaderAdapter(Context context, int maxPreload) {
super(context, maxPreload);
super(maxPreload);
this.context = context;
}
@Override
......@@ -188,7 +190,7 @@ public class ListPreloaderTest extends AndroidTestCase {
@Override
protected Glide.Request getRequest(Object item) {
return Glide.using(new StreamModelLoader<Object>() {
return Glide.with(context).using(new StreamModelLoader<Object>() {
@Override
public ResourceFetcher<InputStream> getResourceFetcher(final Object model, int width, int height) {
return new ResourceFetcher<InputStream>() {
......
......@@ -18,7 +18,7 @@ import com.bumptech.glide.loader.bitmap.model.Cache;
import com.bumptech.glide.loader.bitmap.transformation.CenterCrop;
import com.bumptech.glide.loader.image.ImageManagerLoader;
import com.bumptech.glide.presenter.ImagePresenter;
import com.bumptech.glide.presenter.target.Target;
import com.bumptech.glide.presenter.target.ImageViewTarget;
import com.bumptech.glide.resize.load.Downsampler;
import com.bumptech.glide.samples.flickr.api.Photo;
......@@ -72,9 +72,11 @@ public class FlickrPhotoGrid extends SherlockFragment implements PhotoViewer {
private class FlickrPreloader extends ListPreloader<Photo> {
private final int[] dimens = new int[] { photoSize, photoSize };
private final Context context;
public FlickrPreloader(Context context, int toPreload) {
super(context, toPreload);
super(toPreload);
this.context = context;
}
@Override
......@@ -88,8 +90,9 @@ public class FlickrPhotoGrid extends SherlockFragment implements PhotoViewer {
}
@Override
protected Glide.Request getRequest(Photo item) {
return Glide.using(new FlickrModelLoader(getActivity(), urlCache))
protected Glide.Request<Photo> getRequest(Photo item) {
return Glide.with(context)
.using(new FlickrModelLoader(getActivity(), urlCache))
.load(item)
.centerCrop();
}
......@@ -126,7 +129,7 @@ public class FlickrPhotoGrid extends SherlockFragment implements PhotoViewer {
@Override
public View getView(int position, View view, ViewGroup container) {
final Photo current = photos.get(position);
final ImagePresenter<Photo> imagePresenter;
final ImagePresenter<Photo, ImageViewTarget> imagePresenter;
if (view == null) {
ImageView imageView = (ImageView) inflater.inflate(R.layout.flickr_photo_grid_item, container, false);
ViewGroup.LayoutParams params = imageView.getLayoutParams();
......@@ -135,18 +138,18 @@ public class FlickrPhotoGrid extends SherlockFragment implements PhotoViewer {
final Context context = getActivity();
//this is an example of how one might use ImagePresenter directly, there is otherwise no particular
//reason why ImagePresenter is used here and not in FlickrPhotoList.
// This is an example of how one might use ImagePresenter directly, there is otherwise no particular
// reason why ImagePresenter is used here and not in FlickrPhotoList.
final Animation fadeIn = AnimationUtils.loadAnimation(context, R.anim.fade_in);
imagePresenter = new ImagePresenter.Builder<Photo>()
imagePresenter = new ImagePresenter.Builder<Photo, ImageViewTarget>()
.setBitmapLoadFactory(new BaseBitmapLoadFactory<Photo, InputStream, Void>(
new FlickrModelLoader(context, urlCache), Downsampler.AT_LEAST,
new CenterCrop<Photo>()))
.setImageView(imageView)
.setTarget(new ImageViewTarget(imageView), context)
.setImageLoader(new ImageManagerLoader(context))
.setImageReadyCallback(new ImagePresenter.ImageReadyCallback<Photo>() {
.setImageReadyCallback(new ImagePresenter.ImageReadyCallback<Photo, ImageViewTarget>() {
@Override
public void onImageReady(Photo photo, Target target, boolean fromCache) {
public void onImageReady(Photo photo, ImageViewTarget target, boolean fromCache) {
if (!fromCache) {
target.startAnimation(fadeIn);
}
......@@ -156,7 +159,7 @@ public class FlickrPhotoGrid extends SherlockFragment implements PhotoViewer {
view = imageView;
view.setTag(imagePresenter);
} else {
imagePresenter = (ImagePresenter<Photo>) view.getTag();
imagePresenter = (ImagePresenter<Photo, ImageViewTarget>) view.getTag();
}
imagePresenter.setModel(current);
......
......@@ -13,6 +13,7 @@ import com.actionbarsherlock.app.SherlockFragment;
import com.bumptech.glide.Glide;
import com.bumptech.glide.ListPreloader;
import com.bumptech.glide.loader.bitmap.model.Cache;
import com.bumptech.glide.presenter.target.ImageViewTarget;
import com.bumptech.glide.samples.flickr.api.Photo;
import java.net.URL;
......@@ -50,20 +51,22 @@ public class FlickrPhotoList extends SherlockFragment implements PhotoViewer {
}
private static class ViewHolder {
private final ImageView imageView;
private final TextView titleText;
private final ImageViewTarget imageViewTarget;
public ViewHolder(ImageView imageView, TextView titleText) {
this.imageView = imageView;
this.titleText = titleText;
this.imageViewTarget = new ImageViewTarget(imageView);
}
}
private class FlickrListPreloader extends ListPreloader<Photo> {
private final Context context;
private int[] photoDimens = null;
public FlickrListPreloader(Context context, int maxPreload) {
super(context, maxPreload);
super(maxPreload);
this.context = context;
}
public boolean isDimensSet() {
......@@ -88,7 +91,8 @@ public class FlickrPhotoList extends SherlockFragment implements PhotoViewer {
@Override
protected Glide.Request getRequest(Photo item) {
return Glide.using(new FlickrModelLoader(getActivity(), urlCache))
return Glide.with(context)
.using(new FlickrModelLoader(getActivity(), urlCache))
.load(item)
.centerCrop();
}
......@@ -144,11 +148,12 @@ public class FlickrPhotoList extends SherlockFragment implements PhotoViewer {
viewHolder = (ViewHolder) view.getTag();
}
Glide.using(new FlickrModelLoader(getActivity(), urlCache))
Glide.with(getActivity())
.using(new FlickrModelLoader(getActivity(), urlCache))
.load(current)
.centerCrop()
.animate(R.anim.fade_in)
.into(viewHolder.imageView);
.into(viewHolder.imageViewTarget);
viewHolder.titleText.setText(current.title);
return view;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册