aboutsummaryrefslogtreecommitdiff
path: root/library/src/main
diff options
context:
space:
mode:
authorSam Judd <judds@google.com>2014-10-05 22:03:20 -0700
committerSam Judd <judds@google.com>2014-10-09 07:36:45 -0700
commit7d7d03dceae92dc32a9b84dee665a34c300017a7 (patch)
tree8dc5923108c4827e80d70bd77d5ea2e55d4e5aaf /library/src/main
parent56ecaaaeda884a1976942d89a151ad363eaf9b6c (diff)
downloadglide-7d7d03dceae92dc32a9b84dee665a34c300017a7.tar.gz
Add signature
Fixes #176.
Diffstat (limited to 'library/src/main')
-rw-r--r--library/src/main/java/com/bumptech/glide/BitmapRequestBuilder.java22
-rw-r--r--library/src/main/java/com/bumptech/glide/BitmapTypeRequest.java27
-rw-r--r--library/src/main/java/com/bumptech/glide/DrawableRequestBuilder.java13
-rw-r--r--library/src/main/java/com/bumptech/glide/DrawableTypeRequest.java22
-rw-r--r--library/src/main/java/com/bumptech/glide/GenericRequestBuilder.java51
-rw-r--r--library/src/main/java/com/bumptech/glide/GenericTranscodeRequest.java39
-rw-r--r--library/src/main/java/com/bumptech/glide/GifRequestBuilder.java22
-rw-r--r--library/src/main/java/com/bumptech/glide/GifTypeRequest.java25
-rw-r--r--library/src/main/java/com/bumptech/glide/RequestManager.java205
-rw-r--r--library/src/main/java/com/bumptech/glide/load/Key.java22
-rw-r--r--library/src/main/java/com/bumptech/glide/load/data/MediaStoreThumbFetcher.java15
-rw-r--r--library/src/main/java/com/bumptech/glide/load/engine/Engine.java8
-rw-r--r--library/src/main/java/com/bumptech/glide/load/engine/EngineKey.java34
-rw-r--r--library/src/main/java/com/bumptech/glide/load/engine/EngineKeyFactory.java7
-rw-r--r--library/src/main/java/com/bumptech/glide/load/engine/OriginalKey.java54
-rw-r--r--library/src/main/java/com/bumptech/glide/load/engine/cache/StringKey.java50
-rw-r--r--library/src/main/java/com/bumptech/glide/load/model/stream/MediaStoreStreamLoader.java11
-rw-r--r--library/src/main/java/com/bumptech/glide/request/GenericRequest.java8
-rw-r--r--library/src/main/java/com/bumptech/glide/signature/ApplicationVersionSignature.java63
-rw-r--r--library/src/main/java/com/bumptech/glide/signature/EmptySignature.java26
-rw-r--r--library/src/main/java/com/bumptech/glide/signature/MediaStoreSignature.java65
-rw-r--r--library/src/main/java/com/bumptech/glide/signature/StringSignature.java44
22 files changed, 544 insertions, 289 deletions
diff --git a/library/src/main/java/com/bumptech/glide/BitmapRequestBuilder.java b/library/src/main/java/com/bumptech/glide/BitmapRequestBuilder.java
index ce465ea1..6dc00262 100644
--- a/library/src/main/java/com/bumptech/glide/BitmapRequestBuilder.java
+++ b/library/src/main/java/com/bumptech/glide/BitmapRequestBuilder.java
@@ -1,14 +1,13 @@
package com.bumptech.glide;
-import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.ParcelFileDescriptor;
import android.view.animation.Animation;
import android.widget.ImageView;
-
import com.bumptech.glide.load.DecodeFormat;
import com.bumptech.glide.load.Encoder;
+import com.bumptech.glide.load.Key;
import com.bumptech.glide.load.ResourceDecoder;
import com.bumptech.glide.load.ResourceEncoder;
import com.bumptech.glide.load.Transformation;
@@ -22,8 +21,6 @@ import com.bumptech.glide.load.resource.bitmap.ImageVideoBitmapDecoder;
import com.bumptech.glide.load.resource.bitmap.StreamBitmapDecoder;
import com.bumptech.glide.load.resource.bitmap.VideoBitmapDecoder;
import com.bumptech.glide.load.resource.transcode.ResourceTranscoder;
-import com.bumptech.glide.manager.Lifecycle;
-import com.bumptech.glide.manager.RequestTracker;
import com.bumptech.glide.provider.LoadProvider;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.animation.ViewPropertyAnimation;
@@ -47,18 +44,15 @@ import java.io.InputStream;
public class BitmapRequestBuilder<ModelType, TranscodeType>
extends GenericRequestBuilder<ModelType, ImageVideoWrapper, Bitmap, TranscodeType> implements BitmapOptions {
private final BitmapPool bitmapPool;
- private final Glide glide;
private Downsampler downsampler = Downsampler.AT_LEAST;
private DecodeFormat decodeFormat = DecodeFormat.PREFER_RGB_565;
private ResourceDecoder<InputStream, Bitmap> imageDecoder;
private ResourceDecoder<ParcelFileDescriptor, Bitmap> videoDecoder;
- BitmapRequestBuilder(Context context, ModelType model,
- LoadProvider<ModelType, ImageVideoWrapper, Bitmap, TranscodeType> streamLoadProvider,
- Class<TranscodeType> transcodeClass, Glide glide, RequestTracker requestTracker, Lifecycle lifecycle) {
- super(context, model, streamLoadProvider, transcodeClass, glide, requestTracker, lifecycle);
- this.glide = glide;
- this.bitmapPool = glide.getBitmapPool();
+ BitmapRequestBuilder(LoadProvider<ModelType, ImageVideoWrapper, Bitmap, TranscodeType> loadProvider,
+ Class<TranscodeType> transcodeClass, GenericRequestBuilder<ModelType, ?, ?, ?> other) {
+ super(loadProvider, transcodeClass, other);
+ this.bitmapPool = other.glide.getBitmapPool();
imageDecoder = new StreamBitmapDecoder(bitmapPool);
videoDecoder = new FileDescriptorBitmapDecoder(bitmapPool);
@@ -450,6 +444,12 @@ public class BitmapRequestBuilder<ModelType, TranscodeType>
return this;
}
+ @Override
+ public BitmapRequestBuilder<ModelType, TranscodeType> signature(Key signature) {
+ super.signature(signature);
+ return this;
+ }
+
/**
* {@inheritDoc}
*
diff --git a/library/src/main/java/com/bumptech/glide/BitmapTypeRequest.java b/library/src/main/java/com/bumptech/glide/BitmapTypeRequest.java
index 8e99ef7e..2812e5d6 100644
--- a/library/src/main/java/com/bumptech/glide/BitmapTypeRequest.java
+++ b/library/src/main/java/com/bumptech/glide/BitmapTypeRequest.java
@@ -1,16 +1,12 @@
package com.bumptech.glide;
-import android.content.Context;
import android.graphics.Bitmap;
import android.os.ParcelFileDescriptor;
-
import com.bumptech.glide.load.model.ImageVideoModelLoader;
import com.bumptech.glide.load.model.ImageVideoWrapper;
import com.bumptech.glide.load.model.ModelLoader;
import com.bumptech.glide.load.resource.transcode.BitmapBytesTranscoder;
import com.bumptech.glide.load.resource.transcode.ResourceTranscoder;
-import com.bumptech.glide.manager.Lifecycle;
-import com.bumptech.glide.manager.RequestTracker;
import com.bumptech.glide.provider.DataLoadProvider;
import com.bumptech.glide.provider.FixedLoadProvider;
@@ -24,14 +20,11 @@ import java.io.InputStream;
* @param <ModelType> The type of model to load the {@link Bitmap} or transcoded class from.
*/
public class BitmapTypeRequest<ModelType> extends BitmapRequestBuilder<ModelType, Bitmap> {
- private final Context context;
private final ModelType model;
private final ModelLoader<ModelType, InputStream> streamModelLoader;
private final ModelLoader<ModelType, ParcelFileDescriptor> fileDescriptorModelLoader;
private final Glide glide;
- private final RequestTracker requestTracker;
private final RequestManager.OptionsApplier optionsApplier;
- private final Lifecycle lifecycle;
private static <A, R> FixedLoadProvider<A, ImageVideoWrapper, Bitmap, R> buildProvider(Glide glide,
ModelLoader<A, InputStream> streamModelLoader,
@@ -52,22 +45,16 @@ public class BitmapTypeRequest<ModelType> extends BitmapRequestBuilder<ModelType
return new FixedLoadProvider<A, ImageVideoWrapper, Bitmap, R>(modelLoader, transcoder, loadProvider);
}
- BitmapTypeRequest(Context context, ModelType model,
+ BitmapTypeRequest(GenericRequestBuilder<ModelType, ?, ?, ?> other,
ModelLoader<ModelType, InputStream> streamModelLoader,
ModelLoader<ModelType, ParcelFileDescriptor> fileDescriptorModelLoader,
- Glide glide, RequestTracker requestTracker, Lifecycle lifecycle,
RequestManager.OptionsApplier optionsApplier) {
- super(context, model,
- buildProvider(glide, streamModelLoader, fileDescriptorModelLoader, Bitmap.class, null),
- Bitmap.class,
- glide, requestTracker, lifecycle);
- this.context = context;
- this.model = model;
+ super(buildProvider(other.glide, streamModelLoader, fileDescriptorModelLoader, Bitmap.class, null),
+ Bitmap.class, other);
this.streamModelLoader = streamModelLoader;
this.fileDescriptorModelLoader = fileDescriptorModelLoader;
- this.glide = glide;
- this.requestTracker = requestTracker;
- this.lifecycle = lifecycle;
+ this.model = other.model;
+ this.glide = other.glide;
this.optionsApplier = optionsApplier;
}
@@ -81,9 +68,9 @@ public class BitmapTypeRequest<ModelType> extends BitmapRequestBuilder<ModelType
*/
public <R> BitmapRequestBuilder<ModelType, R> transcode(ResourceTranscoder<Bitmap, R> transcoder,
Class<R> transcodeClass) {
- return optionsApplier.apply(model, new BitmapRequestBuilder<ModelType, R>(context, model,
+ return optionsApplier.apply(model, new BitmapRequestBuilder<ModelType, R>(
buildProvider(glide, streamModelLoader, fileDescriptorModelLoader, transcodeClass, transcoder),
- transcodeClass, glide, requestTracker, lifecycle));
+ transcodeClass, this));
}
/**
diff --git a/library/src/main/java/com/bumptech/glide/DrawableRequestBuilder.java b/library/src/main/java/com/bumptech/glide/DrawableRequestBuilder.java
index 7dde002d..ce01593a 100644
--- a/library/src/main/java/com/bumptech/glide/DrawableRequestBuilder.java
+++ b/library/src/main/java/com/bumptech/glide/DrawableRequestBuilder.java
@@ -5,8 +5,8 @@ import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.view.animation.Animation;
import android.widget.ImageView;
-
import com.bumptech.glide.load.Encoder;
+import com.bumptech.glide.load.Key;
import com.bumptech.glide.load.ResourceDecoder;
import com.bumptech.glide.load.ResourceEncoder;
import com.bumptech.glide.load.Transformation;
@@ -40,16 +40,11 @@ import java.io.File;
public class DrawableRequestBuilder<ModelType>
extends GenericRequestBuilder<ModelType, ImageVideoWrapper, GifBitmapWrapper, GlideDrawable>
implements BitmapOptions, DrawableOptions {
- private final Glide glide;
- private final Context context;
DrawableRequestBuilder(Context context, ModelType model,
LoadProvider<ModelType, ImageVideoWrapper, GifBitmapWrapper, GlideDrawable> loadProvider, Glide glide,
RequestTracker requestTracker, Lifecycle lifecycle) {
super(context, model, loadProvider, GlideDrawable.class, glide, requestTracker, lifecycle);
- this.context = context;
- this.glide = glide;
-
// Default to animating.
crossFade();
}
@@ -402,6 +397,12 @@ public class DrawableRequestBuilder<ModelType>
return this;
}
+ @Override
+ public DrawableRequestBuilder<ModelType> signature(Key signature) {
+ super.signature(signature);
+ return this;
+ }
+
/**
* {@inheritDoc}
*
diff --git a/library/src/main/java/com/bumptech/glide/DrawableTypeRequest.java b/library/src/main/java/com/bumptech/glide/DrawableTypeRequest.java
index 84520056..21c1139f 100644
--- a/library/src/main/java/com/bumptech/glide/DrawableTypeRequest.java
+++ b/library/src/main/java/com/bumptech/glide/DrawableTypeRequest.java
@@ -2,7 +2,6 @@ package com.bumptech.glide;
import android.content.Context;
import android.os.ParcelFileDescriptor;
-
import com.bumptech.glide.load.model.ImageVideoModelLoader;
import com.bumptech.glide.load.model.ImageVideoWrapper;
import com.bumptech.glide.load.model.ModelLoader;
@@ -30,12 +29,7 @@ import java.io.InputStream;
public class DrawableTypeRequest<ModelType> extends DrawableRequestBuilder<ModelType> implements DownloadOptions {
private final ModelLoader<ModelType, InputStream> streamModelLoader;
private final ModelLoader<ModelType, ParcelFileDescriptor> fileDescriptorModelLoader;
- private final Context context;
- private final Glide glide;
- private final RequestTracker requestTracker;
private final RequestManager.OptionsApplier optionsApplier;
- private final Lifecycle lifecycle;
- private final ModelType model;
private static <A, Z, R> FixedLoadProvider<A, ImageVideoWrapper, Z, R> buildProvider(Glide glide,
ModelLoader<A, InputStream> streamModelLoader,
@@ -63,14 +57,9 @@ public class DrawableTypeRequest<ModelType> extends DrawableRequestBuilder<Model
buildProvider(glide, streamModelLoader, fileDescriptorModelLoader, GifBitmapWrapper.class,
GlideDrawable.class, null),
glide, requestTracker, lifecycle);
- this.model = model;
this.streamModelLoader = streamModelLoader;
this.fileDescriptorModelLoader = fileDescriptorModelLoader;
- this.context = context;
- this.glide = glide;
- this.requestTracker = requestTracker;
this.optionsApplier = optionsApplier;
- this.lifecycle = lifecycle;
}
/**
@@ -79,8 +68,8 @@ public class DrawableTypeRequest<ModelType> extends DrawableRequestBuilder<Model
* @return A new request builder for loading a {@link android.graphics.Bitmap}
*/
public BitmapTypeRequest<ModelType> asBitmap() {
- return optionsApplier.apply(model, new BitmapTypeRequest<ModelType>(context, model, streamModelLoader,
- fileDescriptorModelLoader, glide, requestTracker, lifecycle, optionsApplier));
+ return optionsApplier.apply(model, new BitmapTypeRequest<ModelType>(this, streamModelLoader,
+ fileDescriptorModelLoader, optionsApplier));
}
/**
@@ -96,8 +85,7 @@ public class DrawableTypeRequest<ModelType> extends DrawableRequestBuilder<Model
* @return A new request builder for loading a {@link com.bumptech.glide.load.resource.gif.GifDrawable}.
*/
public GifTypeRequest<ModelType> asGif() {
- return optionsApplier.apply(model, new GifTypeRequest<ModelType>(context, model, streamModelLoader, glide,
- requestTracker, lifecycle, optionsApplier));
+ return optionsApplier.apply(model, new GifTypeRequest<ModelType>(this, streamModelLoader, optionsApplier));
}
/**
@@ -115,7 +103,7 @@ public class DrawableTypeRequest<ModelType> extends DrawableRequestBuilder<Model
}
private GenericTranscodeRequest<ModelType, InputStream, File> getDownloadOnlyRequest() {
- return optionsApplier.apply(model, new GenericTranscodeRequest<ModelType, InputStream, File>(context, glide,
- model, streamModelLoader, InputStream.class, File.class, requestTracker, lifecycle, optionsApplier));
+ return optionsApplier.apply(model, new GenericTranscodeRequest<ModelType, InputStream, File>(File.class, this,
+ streamModelLoader, InputStream.class, File.class, optionsApplier));
}
}
diff --git a/library/src/main/java/com/bumptech/glide/GenericRequestBuilder.java b/library/src/main/java/com/bumptech/glide/GenericRequestBuilder.java
index b56c327b..1d3fc690 100644
--- a/library/src/main/java/com/bumptech/glide/GenericRequestBuilder.java
+++ b/library/src/main/java/com/bumptech/glide/GenericRequestBuilder.java
@@ -4,8 +4,9 @@ import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.animation.Animation;
import android.widget.ImageView;
-
+import com.bumptech.glide.signature.EmptySignature;
import com.bumptech.glide.load.Encoder;
+import com.bumptech.glide.load.Key;
import com.bumptech.glide.load.MultiTransformation;
import com.bumptech.glide.load.ResourceDecoder;
import com.bumptech.glide.load.ResourceEncoder;
@@ -49,13 +50,15 @@ import java.io.File;
* @param <TranscodeType> The type of resource the decoded resource will be transcoded to.
*/
public class GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> {
- private final Context context;
- private final ModelType model;
+ protected final Context context;
+ protected final Glide glide;
+ protected final ModelType model;
+ protected final Class<TranscodeType> transcodeClass;
+ protected final RequestTracker requestTracker;
+ protected final Lifecycle lifecycle;
private final ChildLoadProvider<ModelType, DataType, ResourceType, TranscodeType> loadProvider;
- private final Class<TranscodeType> transcodeClass;
- private final Glide glide;
- private final RequestTracker requestTracker;
- private final Lifecycle lifecycle;
+
+ private Key signature = EmptySignature.obtain();
private int placeholderId;
private int errorId;
@@ -74,9 +77,18 @@ public class GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeT
private Transformation<ResourceType> transformation = UnitTransformation.get();
private boolean isTransformationSet;
+ GenericRequestBuilder(LoadProvider<ModelType, DataType, ResourceType, TranscodeType> loadProvider,
+ Class<TranscodeType> transcodeClass, GenericRequestBuilder<ModelType, ?, ?, ?> other) {
+ this(other.context, other.model, loadProvider, transcodeClass, other.glide, other.requestTracker,
+ other.lifecycle);
+ this.signature = other.signature;
+ }
+
GenericRequestBuilder(Context context, ModelType model,
LoadProvider<ModelType, DataType, ResourceType, TranscodeType> loadProvider,
Class<TranscodeType> transcodeClass, Glide glide, RequestTracker requestTracker, Lifecycle lifecycle) {
+ this.context = context;
+ this.model = model;
this.transcodeClass = transcodeClass;
this.glide = glide;
this.requestTracker = requestTracker;
@@ -90,8 +102,6 @@ public class GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeT
if (model != null && loadProvider == null) {
throw new NullPointerException("LoadProvider must not be null");
}
- this.context = context;
- this.model = model;
}
/**
@@ -505,6 +515,28 @@ public class GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeT
}
/**
+ * Sets some additional data to be mixed in to the memory and disk cache keys allowing the caller more control over
+ * when cached data is invalidated.
+ *
+ * <p>
+ * Note - The signature does not replace the cache key, it is purely additive.
+ * </p>
+ *
+ * @see com.bumptech.glide.signature.StringSignature
+ *
+ * @param signature A unique non-null {@link com.bumptech.glide.load.Key} representing the current state of the
+ * model that will be mixed in to the cache key.
+ * @return This request builder.
+ */
+ public GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> signature(Key signature) {
+ if (signature == null) {
+ throw new NullPointerException("Signature must not be null");
+ }
+ this.signature = signature;
+ return this;
+ }
+
+ /**
* Set the target the resource will be loaded into.
*
* @see Glide#clear(com.bumptech.glide.request.target.Target)
@@ -676,6 +708,7 @@ public class GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeT
return GenericRequest.obtain(
loadProvider,
model,
+ signature,
context,
priority,
target,
diff --git a/library/src/main/java/com/bumptech/glide/GenericTranscodeRequest.java b/library/src/main/java/com/bumptech/glide/GenericTranscodeRequest.java
index 9960c06c..4274cb6e 100644
--- a/library/src/main/java/com/bumptech/glide/GenericTranscodeRequest.java
+++ b/library/src/main/java/com/bumptech/glide/GenericTranscodeRequest.java
@@ -1,7 +1,6 @@
package com.bumptech.glide;
import android.content.Context;
-
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.model.ModelLoader;
import com.bumptech.glide.load.resource.transcode.ResourceTranscoder;
@@ -31,15 +30,10 @@ import java.io.File;
*/
public class GenericTranscodeRequest<ModelType, DataType, ResourceType>
extends GenericRequestBuilder<ModelType, DataType, ResourceType, ResourceType> implements DownloadOptions {
- private final Context context;
- private final ModelType model;
- private final Glide glide;
private final ModelLoader<ModelType, DataType> modelLoader;
private final Class<DataType> dataClass;
private final Class<ResourceType> resourceClass;
- private final RequestTracker requestTracker;
private final RequestManager.OptionsApplier optionsApplier;
- private final Lifecycle lifecycle;
private static <A, T, Z, R> LoadProvider<A, T, Z, R> build(Glide glide, ModelLoader<A, T> modelLoader,
Class<T> dataClass, Class<Z> resourceClass, ResourceTranscoder<Z, R> transcoder) {
@@ -47,21 +41,27 @@ public class GenericTranscodeRequest<ModelType, DataType, ResourceType>
return new FixedLoadProvider<A, T, Z, R>(modelLoader, transcoder, dataLoadProvider);
}
+ GenericTranscodeRequest(
+ Class<ResourceType> transcodeClass, GenericRequestBuilder<ModelType, ?, ?, ?> other,
+ ModelLoader<ModelType, DataType> modelLoader, Class<DataType> dataClass, Class<ResourceType> resourceClass,
+ RequestManager.OptionsApplier optionsApplier) {
+ super(build(other.glide, modelLoader, dataClass, resourceClass, UnitTranscoder.<ResourceType>get()),
+ transcodeClass, other);
+ this.modelLoader = modelLoader;
+ this.dataClass = dataClass;
+ this.resourceClass = resourceClass;
+ this.optionsApplier = optionsApplier;
+ }
+
GenericTranscodeRequest(Context context, Glide glide, ModelType model, ModelLoader<ModelType, DataType> modelLoader,
Class<DataType> dataClass, Class<ResourceType> resourceClass, RequestTracker requestTracker,
Lifecycle lifecycle, RequestManager.OptionsApplier optionsApplier) {
- super(context, model,
- build(glide, modelLoader, dataClass, resourceClass, UnitTranscoder.<ResourceType>get()),
+ super(context, model, build(glide, modelLoader, dataClass, resourceClass, UnitTranscoder.<ResourceType>get()),
resourceClass, glide, requestTracker, lifecycle);
- this.context = context;
- this.model = model;
- this.glide = glide;
this.modelLoader = modelLoader;
this.dataClass = dataClass;
this.resourceClass = resourceClass;
- this.requestTracker = requestTracker;
this.optionsApplier = optionsApplier;
- this.lifecycle = lifecycle;
}
/**
@@ -78,8 +78,8 @@ public class GenericTranscodeRequest<ModelType, DataType, ResourceType>
dataClass, resourceClass, transcoder);
return optionsApplier.apply(model,
- new GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType>(context, model,
- loadProvider, transcodeClass, glide, requestTracker, lifecycle));
+ new GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType>(loadProvider,
+ transcodeClass, this));
}
/**
@@ -101,13 +101,10 @@ public class GenericTranscodeRequest<ModelType, DataType, ResourceType>
DataLoadProvider<DataType, File> dataLoadProvider = glide.buildDataProvider(dataClass, File.class);
FixedLoadProvider<ModelType, DataType, File, File> fixedLoadProvider =
new FixedLoadProvider<ModelType, DataType, File, File>(modelLoader, transcoder, dataLoadProvider);
- return optionsApplier.apply(model, new GenericRequestBuilder<ModelType, DataType, File, File>(context, model,
- fixedLoadProvider,
- File.class, glide,
- requestTracker, lifecycle)
+ return optionsApplier.apply(model, new GenericRequestBuilder<ModelType, DataType, File, File>(fixedLoadProvider,
+ File.class, this))
.priority(Priority.LOW)
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
- .skipMemoryCache(true));
-
+ .skipMemoryCache(true);
}
}
diff --git a/library/src/main/java/com/bumptech/glide/GifRequestBuilder.java b/library/src/main/java/com/bumptech/glide/GifRequestBuilder.java
index 1059b7ca..d6918f68 100644
--- a/library/src/main/java/com/bumptech/glide/GifRequestBuilder.java
+++ b/library/src/main/java/com/bumptech/glide/GifRequestBuilder.java
@@ -1,11 +1,10 @@
package com.bumptech.glide;
-import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.view.animation.Animation;
-
import com.bumptech.glide.load.Encoder;
+import com.bumptech.glide.load.Key;
import com.bumptech.glide.load.ResourceDecoder;
import com.bumptech.glide.load.ResourceEncoder;
import com.bumptech.glide.load.Transformation;
@@ -14,8 +13,6 @@ import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
import com.bumptech.glide.load.resource.gif.GifDrawable;
import com.bumptech.glide.load.resource.gif.GifDrawableTransformation;
import com.bumptech.glide.load.resource.transcode.ResourceTranscoder;
-import com.bumptech.glide.manager.Lifecycle;
-import com.bumptech.glide.manager.RequestTracker;
import com.bumptech.glide.provider.LoadProvider;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.animation.DrawableCrossFadeViewAnimation;
@@ -37,15 +34,10 @@ import java.io.InputStream;
public class GifRequestBuilder<ModelType>
extends GenericRequestBuilder<ModelType, InputStream, GifDrawable, GifDrawable>
implements BitmapOptions, DrawableOptions {
- private final Context context;
- private final Glide glide;
- GifRequestBuilder(Context context, ModelType model,
- LoadProvider<ModelType, InputStream, GifDrawable, GifDrawable> loadProvider, Glide glide,
- RequestTracker requestTracker, Lifecycle lifecycle) {
- super(context, model, loadProvider, GifDrawable.class, glide, requestTracker, lifecycle);
- this.context = context;
- this.glide = glide;
+ GifRequestBuilder(LoadProvider<ModelType, InputStream, GifDrawable, GifDrawable> loadProvider,
+ Class<GifDrawable> transcodeClass, GenericRequestBuilder<ModelType, ?, ?, ?> other) {
+ super(loadProvider, transcodeClass, other);
}
/**
@@ -397,6 +389,12 @@ public class GifRequestBuilder<ModelType>
}
@Override
+ public GifRequestBuilder<ModelType> signature(Key signature) {
+ super.signature(signature);
+ return this;
+ }
+
+ @Override
void applyFitCenter() {
fitCenter();
}
diff --git a/library/src/main/java/com/bumptech/glide/GifTypeRequest.java b/library/src/main/java/com/bumptech/glide/GifTypeRequest.java
index 857e516f..bded0f99 100644
--- a/library/src/main/java/com/bumptech/glide/GifTypeRequest.java
+++ b/library/src/main/java/com/bumptech/glide/GifTypeRequest.java
@@ -1,13 +1,9 @@
package com.bumptech.glide;
-import android.content.Context;
-
import com.bumptech.glide.load.model.ModelLoader;
import com.bumptech.glide.load.resource.gif.GifDrawable;
import com.bumptech.glide.load.resource.transcode.GifDrawableBytesTranscoder;
import com.bumptech.glide.load.resource.transcode.ResourceTranscoder;
-import com.bumptech.glide.manager.Lifecycle;
-import com.bumptech.glide.manager.RequestTracker;
import com.bumptech.glide.provider.DataLoadProvider;
import com.bumptech.glide.provider.FixedLoadProvider;
@@ -22,13 +18,8 @@ import java.io.InputStream;
* transcoded class from.
*/
public class GifTypeRequest<ModelType> extends GifRequestBuilder<ModelType> {
- private final Context context;
- private final ModelType model;
private final ModelLoader<ModelType, InputStream> streamModelLoader;
- private final Glide glide;
- private final RequestTracker requestTracker;
private final RequestManager.OptionsApplier optionsApplier;
- private final Lifecycle lifecycle;
private static <A, R> FixedLoadProvider<A, InputStream, GifDrawable, R> buildProvider(Glide glide,
ModelLoader<A, InputStream> streamModelLoader, Class<R> transcodeClass,
@@ -45,17 +36,11 @@ public class GifTypeRequest<ModelType> extends GifRequestBuilder<ModelType> {
return new FixedLoadProvider<A, InputStream, GifDrawable, R>(streamModelLoader, transcoder, dataLoadProvider);
}
- GifTypeRequest(Context context, ModelType model, ModelLoader<ModelType, InputStream> streamModelLoader, Glide glide,
- RequestTracker requestTracker, Lifecycle lifecycle, RequestManager.OptionsApplier optionsApplier) {
- super(context, model, buildProvider(glide, streamModelLoader, GifDrawable.class, null), glide,
- requestTracker, lifecycle);
- this.context = context;
- this.model = model;
+ GifTypeRequest(GenericRequestBuilder<ModelType, ?, ?, ?> other,
+ ModelLoader<ModelType, InputStream> streamModelLoader, RequestManager.OptionsApplier optionsApplier) {
+ super(buildProvider(other.glide, streamModelLoader, GifDrawable.class, null), GifDrawable.class, other);
this.streamModelLoader = streamModelLoader;
- this.glide = glide;
- this.requestTracker = requestTracker;
this.optionsApplier = optionsApplier;
- this.lifecycle = lifecycle;
// Default to animating.
crossFade();
@@ -77,8 +62,8 @@ public class GifTypeRequest<ModelType> extends GifRequestBuilder<ModelType> {
ResourceTranscoder<GifDrawable, R> transcoder, Class<R> transcodeClass) {
FixedLoadProvider<ModelType, InputStream, GifDrawable, R> provider = buildProvider(glide, streamModelLoader,
transcodeClass, transcoder);
- return optionsApplier.apply(model, new GenericRequestBuilder<ModelType, InputStream, GifDrawable, R>(context,
- model, provider, transcodeClass, glide, requestTracker, lifecycle));
+ return optionsApplier.apply(model,
+ new GenericRequestBuilder<ModelType, InputStream, GifDrawable, R>(provider, transcodeClass, this));
}
/**
diff --git a/library/src/main/java/com/bumptech/glide/RequestManager.java b/library/src/main/java/com/bumptech/glide/RequestManager.java
index 3e2b751b..3b6ba991 100644
--- a/library/src/main/java/com/bumptech/glide/RequestManager.java
+++ b/library/src/main/java/com/bumptech/glide/RequestManager.java
@@ -5,7 +5,6 @@ import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.ParcelFileDescriptor;
-
import com.bumptech.glide.load.model.ModelLoader;
import com.bumptech.glide.load.model.file_descriptor.FileDescriptorModelLoader;
import com.bumptech.glide.load.model.stream.MediaStoreStreamLoader;
@@ -36,7 +35,7 @@ import java.util.UUID;
*/
public class RequestManager implements LifecycleListener {
private final Context context;
- private Lifecycle lifecycle;
+ private final Lifecycle lifecycle;
private final RequestTracker requestTracker;
private final Glide glide;
private final OptionsApplier optionsApplier;
@@ -167,98 +166,111 @@ public class RequestManager implements LifecycleListener {
}
/**
- * Use the given generic model loader to load the given generic data class.
+ * Returns a request builder that uses the given {@link com.bumptech.glide.load.model.ModelLoader} to fetch a
+ * generic data type.
+ *
* <p>
* Warning - This is an experimental api that may change without a change in major version.
* </p>
+ *
* @param modelLoader The {@link ModelLoader} class to use to load the model.
* @param dataClass The type of data the {@link ModelLoader} will load.
* @param <A> The type of the model to be loaded.
* @param <T> The type of the data to be loaded from the mode.
- * @return A {@link GenericModelRequest} to set options for the load and ultimately the target to load the model
- * into.
*/
public <A, T> GenericModelRequest<A, T> using(ModelLoader<A, T> modelLoader, Class<T> dataClass) {
return new GenericModelRequest<A, T>(modelLoader, dataClass);
}
/**
- * 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.
+ * Returns a request builder that uses the given {@link com.bumptech.glide.load.model.stream.StreamModelLoader} to
+ * fetch an {@link InputStream} 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>(modelLoader);
}
/**
- * A convenience method to use a {@link StreamByteArrayLoader} to decode an image from a byte array.
+ * Returns a request builder that uses the given
+ * {@link com.bumptech.glide.load.model.stream.StreamByteArrayLoader} to fetch an {@link java.io.InputStream} for
+ * loading Bitmaps.
*
* @param modelLoader The byte array loader.
- * @return A new {@link ImageModelRequest}.
*/
public ImageModelRequest<byte[]> using(StreamByteArrayLoader modelLoader) {
return new ImageModelRequest<byte[]>(modelLoader);
}
/**
- * 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.
+ * Returns a new request builder that uses the given {@link ModelLoader} to fetch a
+ * {@link ParcelFileDescriptor} 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>(modelLoader);
}
/**
- * Use the {@link com.bumptech.glide.load.model.ModelLoaderFactory} currently registered for {@link String} to load
- * the image represented by the given {@link String}. Defaults to
- * {@link com.bumptech.glide.load.model.stream.StreamStringLoader.Factory} and
- * {@link com.bumptech.glide.load.model.stream.StreamStringLoader} to load the given model.
+ * Returns a request builder to load the data represented by the given {@link String} using an empty
+ * signature.
*
- * @see #using(StreamModelLoader)
+ * <p>
+ * Note - this method caches data using only the given String as the cache key. If the data is a Uri outside of
+ * your control, or you otherwise expect the data represented by the given String to change without the String
+ * identifier changing, Consider using
+ * {@link com.bumptech.glide.GenericRequestBuilder#signature(com.bumptech.glide.load.Key)} to mixin a signature
+ * you create that identifies the data currently at the given String that will invalidate the cache if that data
+ * changes. Alternatively, using {@link com.bumptech.glide.load.engine.DiskCacheStrategy#NONE} and/or
+ * {@link com.bumptech.glide.DrawableRequestBuilder#skipMemoryCache(boolean)} may be appropriate.
+ * </p>
*
- * @param string The string representing the image. Must be either a path, or a uri handled by
- * {@link com.bumptech.glide.load.model.stream.StreamUriLoader}
- * @return A {@link DrawableTypeRequest} to set options for the load and ultimately the target to load the model
- * into.
+ * @see com.bumptech.glide.GenericRequestBuilder#signature(com.bumptech.glide.load.Key)
+ *
+ * @param string A file path, or a uri or url handled by {@link com.bumptech.glide.load.model.UriLoader}.
*/
public DrawableTypeRequest<String> load(String string) {
return loadGeneric(string);
}
/**
- * Use the {@link com.bumptech.glide.load.model.ModelLoaderFactory} currently registered for {@link Uri} to load the
- * image at the given uri. Defaults to {@link com.bumptech.glide.load.model.stream.StreamUriLoader.Factory} and
- * {@link com.bumptech.glide.load.model.stream.StreamUriLoader}.
+ * Returns a request builder to load the data represented by the given {@link Uri} using an empty signature.
*
- * @see #using(StreamModelLoader)
+ * <p>
+ * Note - this method caches data at Uris using only the Uri itself as the cache key. The data represented by
+ * Uris from some content providers may change without the Uri changing, which means using this method
+ * can lead to displaying stale data. Consider using
+ * {@link com.bumptech.glide.GenericRequestBuilder#signature(com.bumptech.glide.load.Key)} to mixin a signature
+ * you create based on the data at the given Uri that will invalidate the cache if that data changes.
+ * Alternatively, using {@link com.bumptech.glide.load.engine.DiskCacheStrategy#NONE} and/or
+ * {@link com.bumptech.glide.DrawableRequestBuilder#skipMemoryCache(boolean)} may be appropriate.
+ * </p>
*
- * @param uri The uri representing the image. Must be a uri handled by
- * {@link com.bumptech.glide.load.model.stream.StreamUriLoader}
- * @return A {@link DrawableTypeRequest} to set options for the load and ultimately the target to load the model
- * into.
+ * @see #using(com.bumptech.glide.load.model.stream.StreamModelLoader)
+ * @see #loadFromMediaStore(android.net.Uri)
+ * @see #loadFromMediaStore(android.net.Uri, String, long, int)
+ * @see com.bumptech.glide.GenericRequestBuilder#signature(com.bumptech.glide.load.Key)
+ *
+ * @param uri The Uri representing the image. Must be of a type handled by
+ * {@link com.bumptech.glide.load.model.UriLoader}.
*/
public DrawableTypeRequest<Uri> load(Uri uri) {
return loadGeneric(uri);
}
/**
- * Use {@link android.provider.MediaStore.Images.Thumbnails} and
- * {@link android.provider.MediaStore.Video.Thumbnails} to retrieve pre-generated thumbnails for the given uri.
+ * Returns a request builder that uses {@link android.provider.MediaStore.Images.Thumbnails} and
+ * {@link android.provider.MediaStore.Video.Thumbnails} to retrieve pre-generated thumbnails for the given uri if
+ * available and uses the given additional data to build a unique signature for cache invalidation.
*
- * <p>
- * Falls back to the registered {@link com.bumptech.glide.load.model.ModelLoaderFactory} registered for
- * {@link Uri}s if the given uri is not a media store uri or if no pre-generated thumbnail exists for the given
- * uri. In addition, mixes the given mimeType, dateModified, and orientation into the cache key to detect and
- * invalidate thumbnails if content is changed locally.
- * </p>
+ * @see #loadFromMediaStore(android.net.Uri)
+ * @see #load(android.net.Uri)
+ * @see com.bumptech.glide.GenericRequestBuilder#signature(com.bumptech.glide.load.Key)
+ * @see com.bumptech.glide.signature.MediaStoreSignature
*
* @param uri The uri representing the media.
* @param mimeType The mime type of the media store media. Ok to default to empty string "". See
@@ -269,88 +281,140 @@ public class RequestManager implements LifecycleListener {
* {@link android.provider.MediaStore.Video.VideoColumns#DATE_MODIFIED}.
* @param orientation The orientation of the media store media. Ok to default to 0. See
* {@link android.provider.MediaStore.Images.ImageColumns#ORIENTATION}.
- * @return A new {@link DrawableRequestBuilder} to set options for the load and ultimately the target to load the
- * uri into.
*/
public DrawableTypeRequest<Uri> loadFromMediaStore(Uri uri, String mimeType, long dateModified, int orientation) {
+ // TODO: create a signature from the given arguments.
+ return loadFromMediaStore(uri);
+ }
+
+ /**
+ * Returns a request builder that uses {@link android.provider.MediaStore.Images.Thumbnails} and
+ * {@link android.provider.MediaStore.Video.Thumbnails} to retrieve pre-generated thumbnails for the given uri.
+ *
+ * <p>
+ * Falls back to the registered {@link com.bumptech.glide.load.model.ModelLoaderFactory} registered for
+ * {@link Uri}s if the given uri is not a media store uri or if no pre-generated thumbnail exists for the given
+ * uri.
+ * </p>
+ *
+ * <p>
+ * Note - This method by default caches data using the given Uri as the key. Since content in the media store
+ * can change at any time, you should use
+ * {@link com.bumptech.glide.GenericRequestBuilder#signature(com.bumptech.glide.load.Key)} to mix in some
+ * additional data identifying the current state of the Uri, preferably using
+ * {@link com.bumptech.glide.signature.MediaStoreSignature}. Alternatively consider avoiding the memory and
+ * disk caches entirely using
+ * {@link GenericRequestBuilder#diskCacheStrategy(com.bumptech.glide.load.engine.DiskCacheStrategy)}
+ * and {@link com.bumptech.glide.load.engine.DiskCacheStrategy#NONE} and/or
+ * {@link com.bumptech.glide.GenericRequestBuilder#skipMemoryCache(boolean)}.
+ * </p>
+ *
+ * @see #loadFromMediaStore(android.net.Uri, String, long, int)
+ * @see #load(android.net.Uri)
+ * @see com.bumptech.glide.GenericRequestBuilder#signature(com.bumptech.glide.load.Key)
+ * @see com.bumptech.glide.signature.MediaStoreSignature
+ *
+ * @param uri The uri representing the media.
+ */
+ public DrawableTypeRequest<Uri> loadFromMediaStore(Uri uri) {
ModelLoader<Uri, InputStream> genericStreamLoader = Glide.buildStreamModelLoader(uri, context);
- ModelLoader<Uri, InputStream> mediaStoreLoader = new MediaStoreStreamLoader(context, genericStreamLoader,
- mimeType, dateModified, orientation);
+ ModelLoader<Uri, InputStream> mediaStoreLoader = new MediaStoreStreamLoader(context, genericStreamLoader);
ModelLoader<Uri, ParcelFileDescriptor> fileDescriptorModelLoader = Glide.buildFileDescriptorModelLoader(uri,
context);
- return optionsApplier.apply(uri, new DrawableTypeRequest<Uri>(uri, mediaStoreLoader, fileDescriptorModelLoader,
- context, glide, requestTracker, lifecycle, optionsApplier));
+
+ return optionsApplier.apply(uri, new DrawableTypeRequest<Uri>(uri, mediaStoreLoader,
+ fileDescriptorModelLoader, context, glide, requestTracker, lifecycle, optionsApplier));
}
/**
- * Use the {@link com.bumptech.glide.load.model.ModelLoaderFactory} currently registered for {@link File} to load
- * the image represented by the given {@link File}. Defaults to
+ * Returns a request builder that uses the {@link com.bumptech.glide.load.model.ModelLoaderFactory} currently
+ * registered for {@link File} to load the image represented by the given {@link File}. Defaults to
* {@link com.bumptech.glide.load.model.stream.StreamFileLoader.Factory} and
* {@link com.bumptech.glide.load.model.stream.StreamFileLoader} to load the given model.
*
+ * <p>
+ * Note - this method caches data for Files using only the file path itself as the cache key. The data in the
+ * File can change so using this method can lead to displaying stale data. If you expect the data in the File to
+ * change, Consider using
+ * {@link com.bumptech.glide.GenericRequestBuilder#signature(com.bumptech.glide.load.Key)} to mixin a signature
+ * you create that identifies the data currently in the File that will invalidate the cache if that data
+ * changes. Alternatively, using {@link com.bumptech.glide.load.engine.DiskCacheStrategy#NONE} and/or
+ * {@link com.bumptech.glide.DrawableRequestBuilder#skipMemoryCache(boolean)} may be appropriate.
+ * </p>
+ *
+ * @see #load(java.io.File)
* @see #using(StreamModelLoader)
*
* @param file The File containing the image
- * @return A {@link DrawableTypeRequest} to set options for the load and ultimately the target to load the model
- * into.
*/
public DrawableTypeRequest<File> load(File file) {
return loadGeneric(file);
}
/**
- * Use the {@link com.bumptech.glide.load.model.ModelLoaderFactory} currently registered for {@link Integer} to load
- * the image represented by the given {@link Integer} resource id. Defaults to
- * {@link com.bumptech.glide.load.model.stream.StreamResourceLoader.Factory} and
+ * Returns a request builder that uses the {@link com.bumptech.glide.load.model.ModelLoaderFactory} currently
+ * registered for {@link Integer} to load the image represented by the given {@link Integer} resource id. Defaults
+ * to {@link com.bumptech.glide.load.model.stream.StreamResourceLoader.Factory} and
* {@link com.bumptech.glide.load.model.stream.StreamResourceLoader} to load the given model.
*
+ * <p>
+ * By default this method adds a version code based signature to the cache key used to cache this resource in
+ * Glide. This signature is sufficient to guarantee that end users will see the most up to date versions of
+ * your Drawables, but during development if you do not increment your version code before each install and
+ * you replace a Drawable with different data without changing the Drawable name, you may see inconsistent
+ * cached data. To get around this, consider using {@link com.bumptech.glide.load.engine.DiskCacheStrategy#NONE}
+ * via {@link GenericRequestBuilder#diskCacheStrategy(com.bumptech.glide.load.engine.DiskCacheStrategy)}
+ * during development, and re-enabling the default
+ * {@link com.bumptech.glide.load.engine.DiskCacheStrategy#RESULT} for release builds.
+ * </p>
+ *
+ * @see #load(Integer)
* @see #using(StreamModelLoader)
*
* @param resourceId the id of the resource containing the image
- * @return A {@link DrawableTypeRequest} to set options for the load and ultimately the target to load the model
- * into.
*/
public DrawableTypeRequest<Integer> load(Integer resourceId) {
return loadGeneric(resourceId);
}
/**
- * Use the {@link com.bumptech.glide.load.model.ModelLoaderFactory} currently registered for {@link URL} to load the
- * image represented by the given {@link URL}. Defaults to
+ * Returns a request builder that uses the {@link com.bumptech.glide.load.model.ModelLoaderFactory} currently
+ * registered for {@link URL} to load the image represented by the given {@link URL}. Defaults to
* {@link com.bumptech.glide.load.model.stream.HttpUrlGlideUrlLoader} and
* {@link com.bumptech.glide.load.data.HttpUrlFetcher} to load the given model.
*
* @see #using(StreamModelLoader)
*
* @param url The URL representing the image.
- * @return A {@link DrawableTypeRequest} to set options for the load and ultimately the target to load the model
- * into.
*/
public DrawableTypeRequest<URL> load(URL url) {
return loadGeneric(url);
}
/**
- * Use a new {@link StreamByteArrayLoader} to load an image from the given model.
+ * Returns a request builder that uses a {@link StreamByteArrayLoader} to load an image from the given byte array.
*
* @see #load(byte[])
*
* @param model The data to load.
* @param id A unique id that identifies the image represented by the model suitable for use as a cache key
- * (url, filepath etc). If there is no suitable id, use {@link #load(byte[])} instaed.
+ * (url, filepath etc). If there is no suitable id, use {@link #load(byte[])} instead.
* @return A {@link DrawableTypeRequest} to set options for the load and ultimately the target to load the image
* into.
*/
public DrawableTypeRequest<byte[]> load(byte[] model, final String id) {
final StreamByteArrayLoader loader = new StreamByteArrayLoader(id);
+ // TODO: just use signature instead of id here?
return optionsApplier.apply(model,
new DrawableTypeRequest<byte[]>(model, loader, null, context, glide, requestTracker, lifecycle,
optionsApplier));
}
/**
- * Use a new {@link StreamByteArrayLoader} to load an image from the given model. Suitable when there is no
- * simple id that represents the given data.
+ * Returns a request builder that uses {@link StreamByteArrayLoader} to load an image from the given byte array.
+ * Suitable when there is no simple id that represents the given data.
+ *
+ * @see #load(byte[], String)
*
* @param model the data to load.
* @return A {@link DrawableTypeRequest} to set options for the load and ultimately the target to load the image
@@ -361,14 +425,14 @@ public class RequestManager implements LifecycleListener {
}
/**
- * Use the {@link com.bumptech.glide.load.model.ModelLoaderFactory}s currently registered for the given model type
- * for {@link InputStream}s and {@link ParcelFileDescriptor}s to load a thumbnail from either the image or the video
- * represented by the given model.
+ * Returns a request builder that uses the {@link com.bumptech.glide.load.model.ModelLoaderFactory}s currently
+ * registered for the given model Class for {@link InputStream}s and {@link ParcelFileDescriptor}s to load a
+ * thumbnail from either the image or the video represented by the given model.
+ *
+ * @see #load(Object)
*
* @param model The model the load.
* @param <T> The type of the model to load.
- * @return A {@link DrawableTypeRequest} to set options for the load and ultimately the target to load the image
- * into.
*/
public <T> DrawableTypeRequest<T> load(T model) {
return loadGeneric(model);
@@ -401,8 +465,8 @@ public class RequestManager implements LifecycleListener {
}
public DrawableTypeRequest<T> load(T model) {
- return optionsApplier.apply(model, new DrawableTypeRequest<T>(model, null, loader, context, glide,
- requestTracker, lifecycle, optionsApplier));
+ return optionsApplier.apply(model, new DrawableTypeRequest<T>(model, null, loader, context,
+ glide, requestTracker, lifecycle, optionsApplier));
}
}
@@ -420,8 +484,8 @@ public class RequestManager implements LifecycleListener {
}
public DrawableTypeRequest<T> load(T model) {
- return optionsApplier.apply(model, new DrawableTypeRequest<T>(model, loader, null, context, glide,
- requestTracker, lifecycle, optionsApplier));
+ return optionsApplier.apply(model, new DrawableTypeRequest<T>(model, loader, null, context,
+ glide, requestTracker, lifecycle, optionsApplier));
}
}
@@ -486,7 +550,6 @@ public class RequestManager implements LifecycleListener {
}
return builder;
}
-
}
private static class RequestManagerConnectivityListener implements ConnectivityMonitor.ConnectivityListener {
diff --git a/library/src/main/java/com/bumptech/glide/load/Key.java b/library/src/main/java/com/bumptech/glide/load/Key.java
index 58462256..4f614ed1 100644
--- a/library/src/main/java/com/bumptech/glide/load/Key.java
+++ b/library/src/main/java/com/bumptech/glide/load/Key.java
@@ -4,26 +4,28 @@ import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
/**
- * A very generic interface that must implement {@link Object#equals(Object)} and {@link Object#hashCode()} to include a
- * set of uniquely identifying information for the object(s) represented by this key. Keys are used as cache keys so
- * they must be unique within a given dataset.
- *
+ * An interface that uniquely identifies some set of data. Implementations must implement {@link Object#equals(Object)}
+ * and {@link Object#hashCode()}. Implementations are generally expected to add all uniquely identifying information
+ * used in in {@link java.lang.Object#equals(Object)}} and {@link Object#hashCode()}} to the given
+ * {@link java.security.MessageDigest} in {@link #updateDiskCacheKey(java.security.MessageDigest)}}, although this
+ * requirement is not as strict for partial cache key signatures.
*/
public interface Key {
+ String STRING_CHARSET_NAME = "UTF-8";
+
/**
* Adds all uniquely identifying information to the given digest.
+ *
+ * <p>
+ * Note - Using {@link java.security.MessageDigest#reset()} inside of this method will result in undefined
+ * behavior.
+ * </p>
*/
void updateDiskCacheKey(MessageDigest messageDigest) throws UnsupportedEncodingException;
- /**
- * {@inheritDoc}
- */
@Override
boolean equals(Object o);
- /**
- * {@inheritDoc}
- */
@Override
int hashCode();
}
diff --git a/library/src/main/java/com/bumptech/glide/load/data/MediaStoreThumbFetcher.java b/library/src/main/java/com/bumptech/glide/load/data/MediaStoreThumbFetcher.java
index 2b292a95..af47dd2f 100644
--- a/library/src/main/java/com/bumptech/glide/load/data/MediaStoreThumbFetcher.java
+++ b/library/src/main/java/com/bumptech/glide/load/data/MediaStoreThumbFetcher.java
@@ -30,28 +30,21 @@ public class MediaStoreThumbFetcher implements DataFetcher<InputStream> {
private final DataFetcher<InputStream> defaultFetcher;
private final int width;
private final int height;
- private final long dateModified;
- private final int orientation;
private final ThumbnailStreamOpenerFactory factory;
private InputStream inputStream;
- private String mimeType;
public MediaStoreThumbFetcher(Context context, Uri mediaStoreUri, DataFetcher<InputStream> defaultFetcher,
- int width, int height, String mimeType, long dateModified, int orientation) {
- this(context, mediaStoreUri, defaultFetcher, width, height, mimeType, dateModified, orientation,
- DEFAULT_FACTORY);
+ int width, int height) {
+ this(context, mediaStoreUri, defaultFetcher, width, height, DEFAULT_FACTORY);
}
MediaStoreThumbFetcher(Context context, Uri mediaStoreUri, DataFetcher<InputStream> defaultFetcher, int width,
- int height, String mimeType, long dateModified, int orientation, ThumbnailStreamOpenerFactory factory) {
+ int height, ThumbnailStreamOpenerFactory factory) {
this.context = context;
this.mediaStoreUri = mediaStoreUri;
this.defaultFetcher = defaultFetcher;
this.width = width;
this.height = height;
- this.mimeType = mimeType;
- this.dateModified = dateModified;
- this.orientation = orientation;
this.factory = factory;
}
@@ -84,7 +77,7 @@ public class MediaStoreThumbFetcher implements DataFetcher<InputStream> {
@Override
public String getId() {
- return mediaStoreUri + mimeType + dateModified + orientation;
+ return mediaStoreUri.toString();
}
@Override
diff --git a/library/src/main/java/com/bumptech/glide/load/engine/Engine.java b/library/src/main/java/com/bumptech/glide/load/engine/Engine.java
index abda85e9..c2a6a389 100644
--- a/library/src/main/java/com/bumptech/glide/load/engine/Engine.java
+++ b/library/src/main/java/com/bumptech/glide/load/engine/Engine.java
@@ -118,6 +118,8 @@ public class Engine implements EngineJobListener, MemoryCache.ResourceRemovedLis
* held weakly.
* </p>
*
+ * @param signature A non-null unique key to be mixed into the cache key that identifies the version of the data to
+ * be loaded.
* @param width The target width of the retrieved resource.
* @param height The target height of the retrieved resource.
* @param cacheDecoder The decoder to use to decode data already in the disk cache.
@@ -137,7 +139,7 @@ public class Engine implements EngineJobListener, MemoryCache.ResourceRemovedLis
* @param <Z> The type of the resource that will be decoded.
* @param <R> The type of the resource that will be transcoded from the decoded resource.
*/
- public <T, Z, R> LoadStatus load(int width, int height, ResourceDecoder<File, Z> cacheDecoder,
+ public <T, Z, R> LoadStatus load(Key signature, int width, int height, ResourceDecoder<File, Z> cacheDecoder,
DataFetcher<T> fetcher, Encoder<T> sourceEncoder, ResourceDecoder<T, Z> decoder,
Transformation<Z> transformation, ResourceEncoder<Z> encoder, ResourceTranscoder<Z, R> transcoder,
Priority priority, boolean isMemoryCacheable, DiskCacheStrategy diskCacheStrategy, ResourceCallback cb) {
@@ -145,8 +147,8 @@ public class Engine implements EngineJobListener, MemoryCache.ResourceRemovedLis
long startTime = LogTime.getLogTime();
final String id = fetcher.getId();
- EngineKey key = keyFactory.buildKey(id, width, height, cacheDecoder, decoder, transformation, encoder,
- transcoder, sourceEncoder);
+ EngineKey key = keyFactory.buildKey(id, signature, width, height, cacheDecoder, decoder, transformation,
+ encoder, transcoder, sourceEncoder);
EngineResource<?> cached = getFromCache(key);
if (cached != null) {
diff --git a/library/src/main/java/com/bumptech/glide/load/engine/EngineKey.java b/library/src/main/java/com/bumptech/glide/load/engine/EngineKey.java
index 2755b7ae..7cbbe6f2 100644
--- a/library/src/main/java/com/bumptech/glide/load/engine/EngineKey.java
+++ b/library/src/main/java/com/bumptech/glide/load/engine/EngineKey.java
@@ -5,7 +5,6 @@ import com.bumptech.glide.load.Key;
import com.bumptech.glide.load.ResourceDecoder;
import com.bumptech.glide.load.ResourceEncoder;
import com.bumptech.glide.load.Transformation;
-import com.bumptech.glide.load.engine.cache.StringKey;
import com.bumptech.glide.load.resource.transcode.ResourceTranscoder;
import java.io.UnsupportedEncodingException;
@@ -14,8 +13,6 @@ import java.security.MessageDigest;
@SuppressWarnings("rawtypes")
class EngineKey implements Key {
- private static final String FORMAT = "UTF-8";
-
private final String id;
private final int width;
private final int height;
@@ -25,14 +22,16 @@ class EngineKey implements Key {
private final ResourceEncoder encoder;
private final ResourceTranscoder transcoder;
private final Encoder sourceEncoder;
+ private final Key signature;
private String stringKey;
private int hashCode;
- private StringKey originalKey;
+ private Key originalKey;
- public EngineKey(String id, int width, int height, ResourceDecoder cacheDecoder, ResourceDecoder decoder,
- Transformation transformation, ResourceEncoder encoder, ResourceTranscoder transcoder,
- Encoder sourceEncoder) {
+ public EngineKey(String id, Key signature, int width, int height, ResourceDecoder cacheDecoder,
+ ResourceDecoder decoder, Transformation transformation, ResourceEncoder encoder,
+ ResourceTranscoder transcoder, Encoder sourceEncoder) {
this.id = id;
+ this.signature = signature;
this.width = width;
this.height = height;
this.cacheDecoder = cacheDecoder;
@@ -45,7 +44,7 @@ class EngineKey implements Key {
public Key getOriginalKey() {
if (originalKey == null) {
- originalKey = new StringKey(id);
+ originalKey = new OriginalKey(id, signature);
}
return originalKey;
}
@@ -63,6 +62,8 @@ class EngineKey implements Key {
if (!id.equals(engineKey.id)) {
return false;
+ } else if (!signature.equals(engineKey.signature)) {
+ return false;
} else if (height != engineKey.height) {
return false;
} else if (width != engineKey.width) {
@@ -99,6 +100,7 @@ class EngineKey implements Key {
public int hashCode() {
if (hashCode == 0) {
hashCode = id.hashCode();
+ hashCode = 31 * hashCode + signature.hashCode();
hashCode = 31 * hashCode + width;
hashCode = 31 * hashCode + height;
hashCode = 31 * hashCode + (cacheDecoder != null ? cacheDecoder .getId().hashCode() : 0);
@@ -116,6 +118,7 @@ class EngineKey implements Key {
if (stringKey == null) {
stringKey = new StringBuilder()
.append(id)
+ .append(signature)
.append(width)
.append(height)
.append(cacheDecoder != null ? cacheDecoder .getId() : "")
@@ -135,13 +138,14 @@ class EngineKey implements Key {
.putInt(width)
.putInt(height)
.array();
- messageDigest.update(id.getBytes(FORMAT));
+ signature.updateDiskCacheKey(messageDigest);
+ messageDigest.update(id.getBytes(STRING_CHARSET_NAME));
messageDigest.update(dimensions);
- messageDigest.update((cacheDecoder != null ? cacheDecoder .getId() : "").getBytes(FORMAT));
- messageDigest.update((decoder != null ? decoder .getId() : "").getBytes(FORMAT));
- messageDigest.update((transformation != null ? transformation.getId() : "").getBytes(FORMAT));
- messageDigest.update((encoder != null ? encoder .getId() : "").getBytes(FORMAT));
- // transcoder is not playing in disk cache key, since it's after in the workflow
- messageDigest.update((sourceEncoder != null ? sourceEncoder .getId() : "").getBytes(FORMAT));
+ messageDigest.update((cacheDecoder != null ? cacheDecoder .getId() : "").getBytes(STRING_CHARSET_NAME));
+ messageDigest.update((decoder != null ? decoder .getId() : "").getBytes(STRING_CHARSET_NAME));
+ messageDigest.update((transformation != null ? transformation.getId() : "").getBytes(STRING_CHARSET_NAME));
+ messageDigest.update((encoder != null ? encoder .getId() : "").getBytes(STRING_CHARSET_NAME));
+ // The Transcoder is not included in the disk cache key because its result is not cached.
+ messageDigest.update((sourceEncoder != null ? sourceEncoder .getId() : "").getBytes(STRING_CHARSET_NAME));
}
}
diff --git a/library/src/main/java/com/bumptech/glide/load/engine/EngineKeyFactory.java b/library/src/main/java/com/bumptech/glide/load/engine/EngineKeyFactory.java
index a08c9e4d..029266a7 100644
--- a/library/src/main/java/com/bumptech/glide/load/engine/EngineKeyFactory.java
+++ b/library/src/main/java/com/bumptech/glide/load/engine/EngineKeyFactory.java
@@ -1,6 +1,7 @@
package com.bumptech.glide.load.engine;
import com.bumptech.glide.load.Encoder;
+import com.bumptech.glide.load.Key;
import com.bumptech.glide.load.ResourceDecoder;
import com.bumptech.glide.load.ResourceEncoder;
import com.bumptech.glide.load.Transformation;
@@ -9,11 +10,11 @@ import com.bumptech.glide.load.resource.transcode.ResourceTranscoder;
class EngineKeyFactory {
@SuppressWarnings("rawtypes")
- public EngineKey buildKey(String id, int width, int height, ResourceDecoder cacheDecoder,
+ public EngineKey buildKey(String id, Key signature, int width, int height, ResourceDecoder cacheDecoder,
ResourceDecoder sourceDecoder, Transformation transformation, ResourceEncoder encoder,
ResourceTranscoder transcoder, Encoder sourceEncoder) {
- return new EngineKey(id, width, height, cacheDecoder, sourceDecoder, transformation, encoder, transcoder,
- sourceEncoder);
+ return new EngineKey(id, signature, width, height, cacheDecoder, sourceDecoder, transformation, encoder,
+ transcoder, sourceEncoder);
}
}
diff --git a/library/src/main/java/com/bumptech/glide/load/engine/OriginalKey.java b/library/src/main/java/com/bumptech/glide/load/engine/OriginalKey.java
new file mode 100644
index 00000000..d52e7b60
--- /dev/null
+++ b/library/src/main/java/com/bumptech/glide/load/engine/OriginalKey.java
@@ -0,0 +1,54 @@
+package com.bumptech.glide.load.engine;
+
+import com.bumptech.glide.load.Key;
+
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+
+/**
+ * A class for keeping track of the cache key of the original data + any requested signature.
+ */
+class OriginalKey implements Key {
+
+ private final String id;
+ private final Key signature;
+
+ public OriginalKey(String id, Key signature) {
+ this.id = id;
+ this.signature = signature;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ OriginalKey that = (OriginalKey) o;
+
+ if (!id.equals(that.id)) {
+ return false;
+ }
+ if (!signature.equals(that.signature)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = id.hashCode();
+ result = 31 * result + signature.hashCode();
+ return result;
+ }
+
+ @Override
+ public void updateDiskCacheKey(MessageDigest messageDigest) throws UnsupportedEncodingException {
+ messageDigest.update(id.getBytes(STRING_CHARSET_NAME));
+ signature.updateDiskCacheKey(messageDigest);
+ }
+}
diff --git a/library/src/main/java/com/bumptech/glide/load/engine/cache/StringKey.java b/library/src/main/java/com/bumptech/glide/load/engine/cache/StringKey.java
deleted file mode 100644
index a2f41e48..00000000
--- a/library/src/main/java/com/bumptech/glide/load/engine/cache/StringKey.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.bumptech.glide.load.engine.cache;
-
-import com.bumptech.glide.load.Key;
-
-import java.io.UnsupportedEncodingException;
-import java.security.MessageDigest;
-
-/**
- * A {@link com.bumptech.glide.load.Key} that wraps a single {@link java.lang.String}.
- */
-public class StringKey implements Key {
- private final String key;
-
- public StringKey(String key) {
- this.key = key;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
-
- StringKey stringKey = (StringKey) o;
-
- if (!key.equals(stringKey.key)) {
- return false;
- }
-
- return true;
- }
-
- @Override
- public int hashCode() {
- return key.hashCode();
- }
-
- @Override
- public String toString() {
- return key;
- }
-
- @Override
- public void updateDiskCacheKey(MessageDigest messageDigest) throws UnsupportedEncodingException {
- messageDigest.update(key.getBytes("UTF-8"));
- }
-}
diff --git a/library/src/main/java/com/bumptech/glide/load/model/stream/MediaStoreStreamLoader.java b/library/src/main/java/com/bumptech/glide/load/model/stream/MediaStoreStreamLoader.java
index f311a91e..e069fd77 100644
--- a/library/src/main/java/com/bumptech/glide/load/model/stream/MediaStoreStreamLoader.java
+++ b/library/src/main/java/com/bumptech/glide/load/model/stream/MediaStoreStreamLoader.java
@@ -19,22 +19,15 @@ import java.io.InputStream;
public class MediaStoreStreamLoader implements ModelLoader<Uri, InputStream> {
private final Context context;
private final ModelLoader<Uri, InputStream> uriLoader;
- private final String mimeType;
- private final long dateModified;
- private final int orientation;
- public MediaStoreStreamLoader(Context context, ModelLoader<Uri, InputStream> uriLoader, String mimeType,
- long dateModified, int orientation) {
+ public MediaStoreStreamLoader(Context context, ModelLoader<Uri, InputStream> uriLoader) {
this.context = context;
this.uriLoader = uriLoader;
- this.mimeType = mimeType;
- this.dateModified = dateModified;
- this.orientation = orientation;
}
@Override
public DataFetcher<InputStream> getResourceFetcher(Uri model, int width, int height) {
return new MediaStoreThumbFetcher(context, model, uriLoader.getResourceFetcher(model, width, height), width,
- height, mimeType, dateModified, orientation);
+ height);
}
}
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 77a6da2a..58afc85a 100644
--- a/library/src/main/java/com/bumptech/glide/request/GenericRequest.java
+++ b/library/src/main/java/com/bumptech/glide/request/GenericRequest.java
@@ -5,6 +5,7 @@ import android.graphics.drawable.Drawable;
import android.util.Log;
import com.bumptech.glide.Priority;
import com.bumptech.glide.load.Encoder;
+import com.bumptech.glide.load.Key;
import com.bumptech.glide.load.ResourceDecoder;
import com.bumptech.glide.load.ResourceEncoder;
import com.bumptech.glide.load.Transformation;
@@ -58,6 +59,7 @@ public final class GenericRequest<A, T, Z, R> implements Request, SizeReadyCallb
private final String tag = String.valueOf(hashCode());
+ private Key signature;
private int placeholderResourceId;
private int errorResourceId;
private Context context;
@@ -89,6 +91,7 @@ public final class GenericRequest<A, T, Z, R> implements Request, SizeReadyCallb
public static <A, T, Z, R> GenericRequest<A, T, Z, R> obtain(
LoadProvider<A, T, Z, R> loadProvider,
A model,
+ Key signature,
Context context,
Priority priority,
Target<R> target,
@@ -114,6 +117,7 @@ public final class GenericRequest<A, T, Z, R> implements Request, SizeReadyCallb
}
request.init(loadProvider,
model,
+ signature,
context,
priority,
target,
@@ -159,6 +163,7 @@ public final class GenericRequest<A, T, Z, R> implements Request, SizeReadyCallb
private void init(
LoadProvider<A, T, Z, R> loadProvider,
A model,
+ Key signature,
Context context,
Priority priority,
Target<R> target,
@@ -179,6 +184,7 @@ public final class GenericRequest<A, T, Z, R> implements Request, SizeReadyCallb
DiskCacheStrategy diskCacheStrategy) {
this.loadProvider = loadProvider;
this.model = model;
+ this.signature = signature;
this.context = context;
this.priority = priority;
this.target = target;
@@ -421,7 +427,7 @@ public final class GenericRequest<A, T, Z, R> implements Request, SizeReadyCallb
logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime));
}
loadedFromMemoryCache = true;
- loadStatus = engine.load(width, height, cacheDecoder, dataFetcher, sourceEncoder, decoder,
+ loadStatus = engine.load(signature, width, height, cacheDecoder, dataFetcher, sourceEncoder, decoder,
transformation, encoder, transcoder, priority, isMemoryCacheable, diskCacheStrategy, this);
loadedFromMemoryCache = resource != null;
if (Log.isLoggable(TAG, Log.VERBOSE)) {
diff --git a/library/src/main/java/com/bumptech/glide/signature/ApplicationVersionSignature.java b/library/src/main/java/com/bumptech/glide/signature/ApplicationVersionSignature.java
new file mode 100644
index 00000000..f51736d0
--- /dev/null
+++ b/library/src/main/java/com/bumptech/glide/signature/ApplicationVersionSignature.java
@@ -0,0 +1,63 @@
+package com.bumptech.glide.signature;
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import com.bumptech.glide.load.Key;
+
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * A utility class for obtaining a {@link com.bumptech.glide.load.Key} signature containing the application version
+ * name using {@link android.content.pm.PackageInfo#versionCode}.
+ */
+public final class ApplicationVersionSignature {
+ private static final ConcurrentHashMap<String, Key> PACKAGE_NAME_TO_KEY = new ConcurrentHashMap<String, Key>();
+
+ /**
+ * Returns the signature {@link com.bumptech.glide.load.Key} for version code of the Application of the given
+ * Context.
+ */
+ public static Key obtain(Context context) {
+ String packageName = context.getPackageName();
+ Key result = PACKAGE_NAME_TO_KEY.get(packageName);
+ if (result == null) {
+ Key toAdd = obtainVersionSignature(context);
+ result = PACKAGE_NAME_TO_KEY.putIfAbsent(packageName, toAdd);
+ // There wasn't a previous mapping, so toAdd is now the Key.
+ if (result == null) {
+ result = toAdd;
+ }
+ }
+
+ return result;
+ }
+
+ // Visible for testing.
+ static void reset() {
+ PACKAGE_NAME_TO_KEY.clear();
+ }
+
+ private static Key obtainVersionSignature(Context context) {
+ PackageInfo pInfo = null;
+ try {
+ pInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ // Should never happen.
+ e.printStackTrace();
+ }
+
+ final String versionCode;
+ if (pInfo != null) {
+ versionCode = String.valueOf(pInfo.versionCode);
+ } else {
+ versionCode = UUID.randomUUID().toString();
+ }
+ return new StringSignature(versionCode);
+ }
+
+ private ApplicationVersionSignature() {
+ // Empty for visibility.
+ }
+}
diff --git a/library/src/main/java/com/bumptech/glide/signature/EmptySignature.java b/library/src/main/java/com/bumptech/glide/signature/EmptySignature.java
new file mode 100644
index 00000000..c46c9149
--- /dev/null
+++ b/library/src/main/java/com/bumptech/glide/signature/EmptySignature.java
@@ -0,0 +1,26 @@
+package com.bumptech.glide.signature;
+
+import com.bumptech.glide.load.Key;
+
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+
+/**
+ * An empty key that is always equal to all other empty keys.
+ */
+public final class EmptySignature implements Key {
+ private static final EmptySignature EMPTY_KEY = new EmptySignature();
+
+ public static EmptySignature obtain() {
+ return EMPTY_KEY;
+ }
+
+ private EmptySignature() {
+ // Empty.
+ }
+
+ @Override
+ public void updateDiskCacheKey(MessageDigest messageDigest) throws UnsupportedEncodingException {
+ // Do nothing.
+ }
+}
diff --git a/library/src/main/java/com/bumptech/glide/signature/MediaStoreSignature.java b/library/src/main/java/com/bumptech/glide/signature/MediaStoreSignature.java
new file mode 100644
index 00000000..4774a69b
--- /dev/null
+++ b/library/src/main/java/com/bumptech/glide/signature/MediaStoreSignature.java
@@ -0,0 +1,65 @@
+package com.bumptech.glide.signature;
+
+import com.bumptech.glide.load.Key;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.security.MessageDigest;
+
+/**
+ * A unique signature based on metadata data from the media store that detects common changes to media store files like
+ * edits, rotations, and temporary file replacement.
+ */
+public class MediaStoreSignature implements Key {
+ private final String mimeType;
+ private final long dateModified;
+ private final int orientation;
+
+ public MediaStoreSignature(String mimeType, long dateModified, int orientation) {
+ this.mimeType = mimeType;
+ this.dateModified = dateModified;
+ this.orientation = orientation;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ MediaStoreSignature that = (MediaStoreSignature) o;
+
+ if (dateModified != that.dateModified) {
+ return false;
+ }
+ if (orientation != that.orientation) {
+ return false;
+ }
+ if (mimeType != null ? !mimeType.equals(that.mimeType) : that.mimeType != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = mimeType != null ? mimeType.hashCode() : 0;
+ result = 31 * result + (int) (dateModified ^ (dateModified >>> 32));
+ result = 31 * result + orientation;
+ return result;
+ }
+
+ @Override
+ public void updateDiskCacheKey(MessageDigest messageDigest) throws UnsupportedEncodingException {
+ byte[] data = ByteBuffer.allocate(12)
+ .putLong(dateModified)
+ .putInt(orientation)
+ .array();
+ messageDigest.update(data);
+ messageDigest.update(mimeType.getBytes(STRING_CHARSET_NAME));
+ }
+}
diff --git a/library/src/main/java/com/bumptech/glide/signature/StringSignature.java b/library/src/main/java/com/bumptech/glide/signature/StringSignature.java
new file mode 100644
index 00000000..a5fa2c9f
--- /dev/null
+++ b/library/src/main/java/com/bumptech/glide/signature/StringSignature.java
@@ -0,0 +1,44 @@
+package com.bumptech.glide.signature;
+
+import com.bumptech.glide.load.Key;
+
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+
+/**
+ * A unique Signature that wraps a String.
+ */
+public class StringSignature implements Key {
+ private final String signature;
+
+ public StringSignature(String signature) {
+ if (signature == null) {
+ throw new NullPointerException("Signature cannot be null!");
+ }
+ this.signature = signature;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ StringSignature that = (StringSignature) o;
+
+ return signature.equals(that.signature);
+ }
+
+ @Override
+ public int hashCode() {
+ return signature.hashCode();
+ }
+
+ @Override
+ public void updateDiskCacheKey(MessageDigest messageDigest) throws UnsupportedEncodingException {
+ messageDigest.update(signature.getBytes(STRING_CHARSET_NAME));
+ }
+}