diff options
author | Sam Judd <judds@google.com> | 2014-09-23 07:14:03 -0700 |
---|---|---|
committer | Sam Judd <judds@google.com> | 2014-09-24 18:33:47 -0700 |
commit | f2285a83d5ac3e79383278b91aa21b0a87603cd1 (patch) | |
tree | 67d8e576b9e6acf266ea55a975e142e94a17bff5 /library/src/main/java/com/bumptech | |
parent | e7812093bde705833531b43be2e9dc92adef1f5d (diff) | |
download | glide-f2285a83d5ac3e79383278b91aa21b0a87603cd1.tar.gz |
Add support for recursive thumbnail calls.
Fixes #149
Diffstat (limited to 'library/src/main/java/com/bumptech')
7 files changed, 99 insertions, 68 deletions
diff --git a/library/src/main/java/com/bumptech/glide/GenericRequestBuilder.java b/library/src/main/java/com/bumptech/glide/GenericRequestBuilder.java index 405336bb..5da47ab6 100644 --- a/library/src/main/java/com/bumptech/glide/GenericRequestBuilder.java +++ b/library/src/main/java/com/bumptech/glide/GenericRequestBuilder.java @@ -54,7 +54,8 @@ public class GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeT private final Class<TranscodeType> transcodeClass; private final Glide glide; private final RequestTracker requestTracker; - private Lifecycle lifecycle; + private final Lifecycle lifecycle; + private int placeholderId; private int errorId; private RequestListener<ModelType, TranscodeType> requestListener; @@ -94,21 +95,14 @@ public class GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeT /** * Loads and displays the resource retrieved by the given thumbnail request if it finishes before this request. - * Best used for loading thumbnail resources that are smaller and will be loaded more quickly than the fullsize + * Best used for loading thumbnail resources that are smaller and will be loaded more quickly than the full size * resource. There are no guarantees about the order in which the requests will actually finish. However, if the * thumb request completes after the full request, the thumb resource will never replace the full resource. * * @see #thumbnail(float) * * <p> - * Note - Any options on the main request will not be passed on to the thumbnail request. For example, if - * you want an animation to occur when either the full resource loads or the thumbnail loads, you need to call - * {@link #animate(int)} on both the thumb and the full request. For a simpler thumbnail option, see - * {@link #thumbnail(float)}. - * </p> - * - * <p> - * Only the thumbnail call on the main request will be obeyed. + * Recursive calls to thumbnail are supported. * </p> * * @param thumbnailRequest The request to use to load the thumbnail. @@ -141,7 +135,7 @@ public class GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeT * </p> * * <p> - * Only the thumbnail call on the main request will be obeyed. + * Recursive calls to thumbnail are supported. * </p> * * @param sizeMultiplier The multiplier to apply to the {@link Target}'s dimensions when loading the thumbnail. @@ -613,17 +607,28 @@ public class GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeT // To be implemented by subclasses when possible. } - private Request buildRequest(Target<TranscodeType> target) { - final Request result; + private Priority getThumbnailPriority() { + final Priority result; + if (priority == Priority.LOW) { + result = Priority.NORMAL; + } else if (priority == Priority.NORMAL) { + result = Priority.HIGH; + } else { + result = Priority.IMMEDIATE; + } + return result; + } + private Request buildRequest(Target<TranscodeType> target) { if (priority == null) { priority = Priority.NORMAL; } + return buildRequestRecursive(target, null); + } + private Request buildRequestRecursive(Target<TranscodeType> target, ThumbnailRequestCoordinator parentCoordinator) { if (thumbnailRequestBuilder != null) { - ThumbnailRequestCoordinator requestCoordinator = new ThumbnailRequestCoordinator(); - Request fullRequest = buildRequest(target, sizeMultiplier, priority, requestCoordinator); - + // Recursive case: contains a potentially recursive thumbnail request builder. if (thumbnailRequestBuilder.animationFactory.equals(NoAnimation.getFactory())) { thumbnailRequestBuilder.animationFactory = animationFactory; } @@ -636,48 +641,31 @@ public class GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeT thumbnailRequestBuilder.priority = getThumbnailPriority(); } - Request thumbnailRequest = thumbnailRequestBuilder.buildRequest(target, - thumbnailRequestBuilder.sizeMultiplier, thumbnailRequestBuilder.priority, requestCoordinator); - - requestCoordinator.setRequests(fullRequest, thumbnailRequest); - result = requestCoordinator; + ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator); + Request fullRequest = obtainRequest(target, sizeMultiplier, priority, coordinator); + // Recursively generate thumbnail requests. + Request thumbRequest = thumbnailRequestBuilder.buildRequestRecursive(target, coordinator); + coordinator.setRequests(fullRequest, thumbRequest); + return coordinator; } else if (thumbSizeMultiplier != null) { - ThumbnailRequestCoordinator requestCoordinator = new ThumbnailRequestCoordinator(); - Request fullRequest = buildRequest(target, sizeMultiplier, priority, requestCoordinator); - Request thumbnailRequest = buildRequest(target, thumbSizeMultiplier, getThumbnailPriority(), - requestCoordinator); - requestCoordinator.setRequests(fullRequest, thumbnailRequest); - result = requestCoordinator; + // Base case: thumbnail multiplier generates a thumbnail request, but cannot recurse. + ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator); + Request fullRequest = obtainRequest(target, sizeMultiplier, priority, coordinator); + Request thumbnailRequest = obtainRequest(target, thumbSizeMultiplier, getThumbnailPriority(), coordinator); + coordinator.setRequests(fullRequest, thumbnailRequest); + return coordinator; } else { - result = buildRequest(target, sizeMultiplier, priority, null); + // Base case: no thumbnail. + return obtainRequest(target, sizeMultiplier, priority, parentCoordinator); } - return result; } - private Priority getThumbnailPriority() { - final Priority result; - if (priority == Priority.LOW) { - result = Priority.NORMAL; - } else if (priority == Priority.NORMAL) { - result = Priority.HIGH; - } else { - result = Priority.IMMEDIATE; - } - return result; - } - - private Request buildRequest(Target<TranscodeType> target, float sizeMultiplier, Priority priority, + private <Z> Request obtainRequest(Target<TranscodeType> target, float sizeMultiplier, Priority priority, RequestCoordinator requestCoordinator) { if (model == null) { - return buildRequestForDataType(target, loadProvider, sizeMultiplier, priority, null); - } else { - return buildRequestForDataType(target, loadProvider, sizeMultiplier, priority, requestCoordinator); + requestCoordinator = null; } - } - private <Z> Request buildRequestForDataType(Target<TranscodeType> target, - LoadProvider<ModelType, Z, ResourceType, TranscodeType> loadProvider, float sizeMultiplier, - Priority priority, RequestCoordinator requestCoordinator) { return GenericRequest.obtain( loadProvider, model, diff --git a/library/src/main/java/com/bumptech/glide/load/engine/SourceResourceRunner.java b/library/src/main/java/com/bumptech/glide/load/engine/SourceResourceRunner.java index acf38865..2dd3ff1e 100644 --- a/library/src/main/java/com/bumptech/glide/load/engine/SourceResourceRunner.java +++ b/library/src/main/java/com/bumptech/glide/load/engine/SourceResourceRunner.java @@ -143,7 +143,8 @@ class SourceResourceRunner<T, Z, R> implements Runnable, Prioritized { if (decoded == null) { decoded = decodeFromSource(); if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "Decoded from source in " + (SystemClock.currentThreadTimeMillis() - start) + " cache"); + Log.v(TAG, "Decoded from source in " + (SystemClock.currentThreadTimeMillis() - start) + " key: " + + key); start = SystemClock.currentThreadTimeMillis(); } } @@ -155,7 +156,7 @@ class SourceResourceRunner<T, Z, R> implements Runnable, Prioritized { decoded.recycle(); } if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "transformed in " + (SystemClock.currentThreadTimeMillis() - start)); + Log.v(TAG, "transformed in " + (SystemClock.currentThreadTimeMillis() - start) + " key: " + key); } } @@ -167,7 +168,7 @@ class SourceResourceRunner<T, Z, R> implements Runnable, Prioritized { start = SystemClock.currentThreadTimeMillis(); transcoded = transcoder.transcode(transformed); if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.d(TAG, "transcoded in " + (SystemClock.currentThreadTimeMillis() - start)); + Log.d(TAG, "transcoded in " + (SystemClock.currentThreadTimeMillis() - start) + " key: " + key); } } return transcoded; diff --git a/library/src/main/java/com/bumptech/glide/request/GenericRequest.java b/library/src/main/java/com/bumptech/glide/request/GenericRequest.java index 999e464b..4f729421 100644 --- a/library/src/main/java/com/bumptech/glide/request/GenericRequest.java +++ b/library/src/main/java/com/bumptech/glide/request/GenericRequest.java @@ -338,6 +338,17 @@ public final class GenericRequest<A, T, Z, R> implements Request, SizeReadyCallb return status == Status.COMPLETE; } + /** + * {@inheritDoc} + */ + @Override + public boolean isResourceSet() { + return isComplete(); + } + + /** + * {@inheritDoc} + */ @Override public boolean isCancelled() { return status == Status.CANCELLED; @@ -428,7 +439,7 @@ public final class GenericRequest<A, T, Z, R> implements Request, SizeReadyCallb } private boolean isFirstReadyResource() { - return requestCoordinator == null || !requestCoordinator.isAnyRequestComplete(); + return requestCoordinator == null || !requestCoordinator.isAnyResourceSet(); } /** diff --git a/library/src/main/java/com/bumptech/glide/request/Request.java b/library/src/main/java/com/bumptech/glide/request/Request.java index b1c4e917..9dbf1d17 100644 --- a/library/src/main/java/com/bumptech/glide/request/Request.java +++ b/library/src/main/java/com/bumptech/glide/request/Request.java @@ -37,6 +37,12 @@ public interface Request { public boolean isComplete(); /** + * Returns true if a non-placeholder resource is set. For Requests that load more than one resource, isResourceSet + * may return true even if {@link #isComplete()}} returns false. + */ + public boolean isResourceSet(); + + /** * Returns true if the request has been cancelled. */ public boolean isCancelled(); diff --git a/library/src/main/java/com/bumptech/glide/request/RequestCoordinator.java b/library/src/main/java/com/bumptech/glide/request/RequestCoordinator.java index 0592559d..47b77daf 100644 --- a/library/src/main/java/com/bumptech/glide/request/RequestCoordinator.java +++ b/library/src/main/java/com/bumptech/glide/request/RequestCoordinator.java @@ -24,5 +24,5 @@ public interface RequestCoordinator { * * @see Request#isComplete() */ - public boolean isAnyRequestComplete(); + public boolean isAnyResourceSet(); } diff --git a/library/src/main/java/com/bumptech/glide/request/ThumbnailRequestCoordinator.java b/library/src/main/java/com/bumptech/glide/request/ThumbnailRequestCoordinator.java index d7033e45..948c62a5 100644 --- a/library/src/main/java/com/bumptech/glide/request/ThumbnailRequestCoordinator.java +++ b/library/src/main/java/com/bumptech/glide/request/ThumbnailRequestCoordinator.java @@ -7,6 +7,15 @@ package com.bumptech.glide.request; public class ThumbnailRequestCoordinator implements RequestCoordinator, Request { private Request full; private Request thumb; + private RequestCoordinator coordinator; + + public ThumbnailRequestCoordinator() { + this(null); + } + + public ThumbnailRequestCoordinator(RequestCoordinator coordinator) { + this.coordinator = coordinator; + } public void setRequests(Request full, Request thumb) { this.full = full; @@ -14,14 +23,19 @@ public class ThumbnailRequestCoordinator implements RequestCoordinator, Request } /** + * * Returns true if the request is either the request loading the fullsize image or if the request loading the - * fullsize image has not yet completed. + * full size image has not yet completed. * * @param request {@inheritDoc} */ @Override public boolean canSetImage(Request request) { - return request == full || !full.isComplete(); + return parentCanSetImage() && (request == full || !full.isResourceSet()); + } + + private boolean parentCanSetImage() { + return coordinator == null || coordinator.canSetImage(this); } /** @@ -32,16 +46,20 @@ public class ThumbnailRequestCoordinator implements RequestCoordinator, Request */ @Override public boolean canNotifyStatusChanged(Request request) { - return request == full && !isAnyRequestComplete(); + return parentCanNotifyStatusChanged() && (request == full && !isAnyResourceSet()); + } + + private boolean parentCanNotifyStatusChanged() { + return coordinator == null || coordinator.canNotifyStatusChanged(this); } - /** - * Returns true if either the full request has completed successfully or the thumb request has completed - * successfully. - */ @Override - public boolean isAnyRequestComplete() { - return full.isComplete() || thumb.isComplete(); + public boolean isAnyResourceSet() { + return parentIsAnyResourceSet() || isResourceSet(); + } + + private boolean parentIsAnyResourceSet() { + return coordinator != null && coordinator.isAnyResourceSet(); } /** @@ -90,7 +108,12 @@ public class ThumbnailRequestCoordinator implements RequestCoordinator, Request */ @Override public boolean isComplete() { - return full.isComplete(); + return full.isComplete() || thumb.isComplete(); + } + + @Override + public boolean isResourceSet() { + return full.isResourceSet() || thumb.isResourceSet(); } @Override diff --git a/library/src/main/java/com/bumptech/glide/request/target/ViewTarget.java b/library/src/main/java/com/bumptech/glide/request/target/ViewTarget.java index fb20e58a..1091786b 100644 --- a/library/src/main/java/com/bumptech/glide/request/target/ViewTarget.java +++ b/library/src/main/java/com/bumptech/glide/request/target/ViewTarget.java @@ -7,12 +7,11 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.WindowManager; - import com.bumptech.glide.request.Request; import java.lang.ref.WeakReference; -import java.util.HashSet; -import java.util.Set; +import java.util.ArrayList; +import java.util.List; /** * A base {@link Target} for loading {@link android.graphics.Bitmap}s into {@link View}s that provides default @@ -112,7 +111,7 @@ public abstract class ViewTarget<T extends View, Z> extends BaseTarget<Z> { private static class SizeDeterminer { private final View view; - private Set<SizeReadyCallback> cbs = new HashSet<SizeReadyCallback>(); + private List<SizeReadyCallback> cbs = new ArrayList<SizeReadyCallback>(); private SizeDeterminerLayoutListener layoutListener; public SizeDeterminer(View view) { @@ -173,6 +172,9 @@ public abstract class ViewTarget<T extends View, Z> extends BaseTarget<Z> { } cb.onSizeReady(width, height); } else { + if (cbs.contains(cb)) { + throw new IllegalArgumentException("Cannot add a callback twice"); + } cbs.add(cb); final ViewTreeObserver observer = view.getViewTreeObserver(); layoutListener = new SizeDeterminerLayoutListener(this); |