提交 0ba0245a 编写于 作者: S Sam Judd

Add BitmapRequest as ImagePresenter replacement.

上级 1ab791a7
......@@ -41,7 +41,7 @@ public abstract class ListPreloader<T> implements AbsListView.OnScrollListener {
*/
public ListPreloader(int maxPreload) {
this.maxPreload = maxPreload;
preloadTargetQueue = new PreloadTargetQueue(maxPreload);
preloadTargetQueue = new PreloadTargetQueue(maxPreload + 1);
}
@Override
......@@ -83,9 +83,9 @@ public abstract class ListPreloader<T> implements AbsListView.OnScrollListener {
* target and context will be provided by the preloader.
*
* @param item The model to load.
* @return A non null {@link Glide.Request}.
* @return A non null {@link Glide.RequestBuilder}.
*/
protected abstract Glide.Request getRequest(T item);
protected abstract Glide.RequestBuilder getRequest(T item);
private void preload(int start, boolean increasing) {
if (isIncreasing != increasing) {
......@@ -111,13 +111,13 @@ public abstract class ListPreloader<T> implements AbsListView.OnScrollListener {
if (from < to) {
// Increasing
final int numItems = items.size();
for (int i = 0; i < numItems; i++) {
for (int i = items.size() - 1; i >= 0; i--) {
preloadItem(items, i);
}
} else {
// Decreasing
for (int i = items.size() - 1; i >= 0; i--) {
final int numItems = items.size();
for (int i = 0; i < numItems; i++) {
preloadItem(items, i);
}
}
......
......@@ -7,6 +7,8 @@ import android.view.animation.Animation;
import com.bumptech.glide.Glide;
import com.bumptech.glide.presenter.ImagePresenter;
import com.bumptech.glide.presenter.Presenter;
import com.bumptech.glide.resize.BitmapRequest;
import com.bumptech.glide.resize.Request;
/**
* A base {@link Target} for loading {@link Bitmap}s that provides basic or empty implementations for most methods.
......@@ -23,6 +25,7 @@ import com.bumptech.glide.presenter.Presenter;
public abstract class BaseTarget implements Target {
private Presenter presenter;
private Request request;
@Override
public void setPresenter(Presenter presenter) {
......@@ -34,6 +37,16 @@ public abstract class BaseTarget implements Target {
return presenter;
}
@Override
public void setRequest(Request request) {
this.request = request;
}
@Override
public Request getRequest() {
return request;
}
@Override
public void setPlaceholder(Drawable placeholder) { }
......
......@@ -5,6 +5,8 @@ import android.graphics.drawable.Drawable;
import android.view.animation.Animation;
import com.bumptech.glide.presenter.ImagePresenter;
import com.bumptech.glide.presenter.Presenter;
import com.bumptech.glide.resize.BitmapRequest;
import com.bumptech.glide.resize.Request;
/**
* An interface that Glide can load an image into
......@@ -50,4 +52,8 @@ public interface Target {
public void setPresenter(Presenter presenter);
public Presenter getPresenter();
public void setRequest(Request request);
public Request getRequest();
}
......@@ -12,6 +12,8 @@ import android.view.animation.Animation;
import android.widget.ListView;
import com.bumptech.glide.presenter.ImagePresenter;
import com.bumptech.glide.presenter.Presenter;
import com.bumptech.glide.resize.BitmapRequest;
import com.bumptech.glide.resize.Request;
import java.lang.ref.WeakReference;
import java.util.HashSet;
......@@ -80,6 +82,16 @@ public abstract class ViewTarget<T extends View> implements Target {
return presenter;
}
@Override
public void setRequest(Request request) {
view.setTag(request);
}
@Override
public Request getRequest() {
return (Request) view.getTag();
}
private static class SizeDeterminer {
private final View view;
private Set<SizeReadyCallback> cbs = new HashSet<SizeReadyCallback>();
......
package com.bumptech.glide.resize;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import com.bumptech.glide.Glide;
import com.bumptech.glide.loader.bitmap.BitmapLoadFactory;
import com.bumptech.glide.presenter.target.Target;
/**
* A {@link Request} that loads an {@link Bitmap} into a given {@link Target}.
*
* @param <T> The type of the model that the {@link Bitmap} will be loaded from.
*/
public class BitmapRequest<T> implements Request, LoadedCallback, Target.SizeReadyCallback {
private static final String TAG = "BitmapRequest";
private final int placeholderResourceId;
private final int errorResourceId;
private final Context context;
private Animation animation;
private final int animationId;
private final RequestCoordinator requestCoordinator;
private final T model;
private final BitmapLoadFactory<T> bitmapLoadFactory;
private final ImageManager imageManager;
private final Priority priority;
private final Target target;
private final Glide.RequestListener<T> requestListener;
private final float sizeMultiplier;
private Drawable placeholderDrawable;
private Drawable errorDrawable;
private boolean isCancelled;
private boolean isError;
private boolean loadedFromMemoryCache;
private Bitmap bitmap;
private ImageManager.LoadToken token;
public BitmapRequest(BitmapRequestBuilder<T> builder) {
this.model = builder.model;
this.context = builder.context.getApplicationContext();
this.bitmapLoadFactory = builder.bitmapLoadFactory;
this.imageManager = builder.imageManager;
this.priority = builder.priority;
this.target = builder.target;
this.sizeMultiplier = builder.sizeMultiplier;
this.placeholderDrawable = builder.placeholderDrawable;
this.placeholderResourceId = builder.placeholderResourceId;
this.errorDrawable = builder.errorDrawable;
this.errorResourceId = builder.errorResourceId;
this.requestListener = builder.requestListener;
this.animationId = builder.animationId;
this.animation = builder.animation;
this.requestCoordinator = builder.requestCoordinator;
}
@Override
public void run() {
loadedFromMemoryCache = true;
target.getSize(this);
loadedFromMemoryCache = bitmap != null;
if (bitmap == null && !isError) {
resetPlaceHolder();
}
}
public void cancel() {
isCancelled = true;
if (token != null) {
token.cancel();
}
}
public void clear() {
cancel();
resetPlaceHolder();
if (bitmap != null) {
imageManager.releaseBitmap(bitmap);
bitmap = null;
}
}
@Override
public boolean isComplete() {
return bitmap != null;
}
private void resetPlaceHolder() {
if (!canSetPlaceholder()) return;
if (placeholderDrawable == null && placeholderResourceId != 0) {
placeholderDrawable = context.getResources().getDrawable(placeholderResourceId);
}
target.setPlaceholder(placeholderDrawable);
}
@Override
public void onLoadCompleted(Bitmap loaded) {
if (isCancelled || !canSetImage()) {
imageManager.releaseBitmap(loaded);
return;
}
target.onImageReady(loaded);
if (!loadedFromMemoryCache && !isAnyImageSet()) {
if (animation == null && animationId != 0) {
animation = AnimationUtils.loadAnimation(context, animationId);
}
if (animation != null) {
target.startAnimation(animation);
}
}
if (requestListener != null) {
requestListener.onImageReady(model, target, loadedFromMemoryCache, isAnyImageSet());
}
bitmap = loaded;
}
@Override
public void onLoadFailed(Exception e) {
if (isCancelled) {
return;
} else {
Log.e(TAG, "load failed", e);
}
isError = true;
if (canSetPlaceholder()) {
if (errorDrawable == null && errorResourceId != 0) {
errorDrawable = context.getResources().getDrawable(errorResourceId);
}
target.setPlaceholder(errorDrawable);
}
//TODO: what if this is a thumbnail request?
if (requestListener != null) {
requestListener.onException(e, model, target);
}
}
@Override
public void onSizeReady(int width, int height) {
// This should only be called once.
if (isCancelled) {
return;
}
width = Math.round(sizeMultiplier * width);
height = Math.round(sizeMultiplier * height);
BitmapLoad loadTask = bitmapLoadFactory.getLoadTask(model, width, height);
if (loadTask == null) {
if (Log.isLoggable(TAG, Log.INFO)) {
Log.i(TAG, "got null load task for model=" + model);
}
clear();
return;
}
loadTask.setMetadata(new Metadata(priority));
token = imageManager.getImage(loadTask, this);
}
private boolean canSetImage() {
return requestCoordinator == null || requestCoordinator.canSetImage(this);
}
private boolean canSetPlaceholder() {
return requestCoordinator == null || requestCoordinator.canSetPlaceholder(this);
}
private boolean isAnyImageSet() {
return requestCoordinator != null && requestCoordinator.isAnyRequestComplete();
}
}
package com.bumptech.glide.resize;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.view.animation.Animation;
import com.bumptech.glide.Glide;
import com.bumptech.glide.loader.bitmap.BitmapLoadFactory;
import com.bumptech.glide.presenter.target.Target;
/**
* A simple builder class for {@link BitmapRequest}.
*
* @param <T> The model type the {@link BitmapRequest} will load a {@link Bitmap} from.
*/
public class BitmapRequestBuilder<T> {
T model;
BitmapLoadFactory<T> bitmapLoadFactory;
ImageManager imageManager;
Target target;
Priority priority;
float sizeMultiplier;
Drawable placeholderDrawable;
Drawable errorDrawable;
Glide.RequestListener<T> requestListener;
Animation animation;
int placeholderResourceId;
int errorResourceId;
Context context;
RequestCoordinator requestCoordinator;
int animationId;
public BitmapRequestBuilder<T> setModel(T model) {
this.model = model;
return this;
}
public BitmapRequestBuilder<T> setContext(Context context) {
this.context = context;
return this;
}
public BitmapRequestBuilder<T> setBitmapLoadFactory(BitmapLoadFactory<T> bitmapLoadFactory) {
this.bitmapLoadFactory = bitmapLoadFactory;
return this;
}
public BitmapRequestBuilder<T> setImageManager(ImageManager imageManager) {
this.imageManager = imageManager;
return this;
}
public BitmapRequestBuilder<T> setTarget(Target target) {
this.target = target;
return this;
}
public BitmapRequestBuilder<T> setPriority(Priority priority) {
this.priority = priority;
return this;
}
public BitmapRequestBuilder<T> setSizeMultiplier(float sizeMultiplier) {
this.sizeMultiplier = sizeMultiplier;
return this;
}
public BitmapRequestBuilder<T> setRequestListener(Glide.RequestListener<T> requestListener) {
this.requestListener = requestListener;
return this;
}
public BitmapRequestBuilder<T> setAnimation(int animationId) {
this.animationId = animationId;
return this;
}
public BitmapRequestBuilder<T> setAnimation(Animation animation) {
this.animation = animation;
return this;
}
public BitmapRequestBuilder<T> setPlaceholderResource(int resourceId) {
this.placeholderResourceId = resourceId;
return this;
}
public BitmapRequestBuilder<T> setPlaceholderDrawable(Drawable placeholderDrawable) {
this.placeholderDrawable = placeholderDrawable;
return this;
}
public BitmapRequestBuilder<T> setErrorResource(int resourceId) {
this.errorResourceId = resourceId;
return this;
}
public BitmapRequestBuilder<T> setErrorDrawable(Drawable errorDrawable) {
this.errorDrawable = errorDrawable;
return this;
}
public BitmapRequestBuilder<T> setRequestCoordinator(RequestCoordinator requestCoordinator) {
this.requestCoordinator = requestCoordinator;
return this;
}
public BitmapRequest<T> build() {
return new BitmapRequest<T>(this);
}
}
\ No newline at end of file
package com.bumptech.glide.resize;
import com.bumptech.glide.presenter.target.Target;
/**
* A request that loads an asset for an {@link Target}.
*/
public interface Request {
/**
* Starts an asynchronous load.
*/
public void run();
/**
* Prevents any bitmaps being loaded from previous requests, releases any resources held by this request and
* displays the current placeholder if one was provided.
*/
public void clear();
/**
* Returns true if the request has successfully completed.
*/
public boolean isComplete();
}
package com.bumptech.glide.resize;
import com.bumptech.glide.resize.target.Target;
/**
* An interface for coordinating multiple requests with the same {@link Target}.
*/
public interface RequestCoordinator {
/**
* Returns true if the {@link Request} can display a loaded bitmap.
*
* @param request The {@link Request} requesting permission to display a bitmap.
*/
public boolean canSetImage(Request request);
/**
* Returns true if the {@link Request} can display a placeholder.
*
* @param request The {@link Request} requesting permission to display a placeholder.
*/
public boolean canSetPlaceholder(Request request);
/**
* Returns true if any coordinated {@link Request} has successfully completed.
*
* @see Request#isComplete()
*/
public boolean isAnyRequestComplete();
}
package com.bumptech.glide.resize;
/**
* A coordinator that coordinates two individual {@link Request}s that load a small thumbnail version of an image and
* the full size version of the image at the same time.
*/
public class ThumbnailRequestCoordinator implements RequestCoordinator, Request {
private Request full;
private Request thumb;
public void setRequests(Request full, Request thumb) {
this.full = full;
this.thumb = thumb;
}
@Override
public boolean canSetImage(Request request) {
return request == full || !full.isComplete();
}
@Override
public boolean canSetPlaceholder(Request request) {
return request == full;
}
@Override
public boolean isAnyRequestComplete() {
return full.isComplete() || thumb.isComplete();
}
@Override
public void run() {
full.run();
if (!full.isComplete()) {
thumb.run();
}
}
@Override
public void clear() {
full.clear();
thumb.clear();
}
@Override
public boolean isComplete() {
return full.isComplete();
}
}
......@@ -154,7 +154,7 @@ public class ListPreloaderTest extends AndroidTestCase {
}
@Override
protected Glide.Request getRequest(Object item) {
protected Glide.RequestBuilder getRequest(Object item) {
loadedObjects.add(item);
return super.getRequest(item);
}
......@@ -190,7 +190,7 @@ public class ListPreloaderTest extends AndroidTestCase {
}
@Override
protected Glide.Request getRequest(Object item) {
protected Glide.RequestBuilder getRequest(Object item) {
return Glide.with(context).using(new StreamModelLoader<Object>() {
@Override
public ResourceFetcher<InputStream> getResourceFetcher(final Object model, int width, int height) {
......
......@@ -91,7 +91,7 @@ public class FlickrPhotoGrid extends SherlockFragment implements PhotoViewer {
}
@Override
protected Glide.Request<Photo> getRequest(Photo item) {
protected Glide.RequestBuilder<Photo> getRequest(Photo item) {
return Glide.with(context)
.using(new FlickrModelLoader(getActivity(), urlCache))
.load(item)
......
......@@ -13,7 +13,6 @@ 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.Target;
import com.bumptech.glide.samples.flickr.api.Photo;
import java.net.URL;
......@@ -92,7 +91,7 @@ public class FlickrPhotoList extends SherlockFragment implements PhotoViewer {
}
@Override
protected Glide.Request getRequest(Photo item) {
protected Glide.RequestBuilder getRequest(Photo item) {
return Glide.with(context)
.using(new FlickrModelLoader(getActivity(), urlCache))
.load(item)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册