下面列出了怎么用com.bumptech.glide.load.Key的API类实例代码及写法,或者点击链接到github查看源代码。
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);
}
public <Z> Resource<Z> load(Key key, ResourceDecoder<File, Z> decoder, int width, int height) {
File fromCache = diskCache.get(key);
if (fromCache == null) {
return null;
}
Resource<Z> result = null;
try {
result = decoder.decode(fromCache, width, height);
} catch (IOException e) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Exception decoding image from cache", e);
}
}
if (result == null) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Failed to decode image from cache or not present in cache");
}
diskCache.delete(key);
}
return result;
}
private Resource<T> loadFromCache(Key key) throws IOException {
File cacheFile = diskCacheProvider.getDiskCache().get(key);
if (cacheFile == null) {
return null;
}
Resource<T> result = null;
try {
result = loadProvider.getCacheDecoder().decode(cacheFile, width, height);
} finally {
if (result == null) {
diskCacheProvider.getDiskCache().delete(key);
}
}
return result;
}
private EngineResource<?> loadFromActiveResources(Key key, boolean isMemoryCacheable) {
if (!isMemoryCacheable) {
return null;
}
EngineResource<?> active = null;
WeakReference<EngineResource<?>> activeRef = activeResources.get(key);
if (activeRef != null) {
active = activeRef.get();
if (active != null) {
active.acquire();
} else {
activeResources.remove(key);
}
}
return active;
}
@Override
public File get(Key key) {
String safeKey = safeKeyGenerator.getSafeKey(key);
File result = null;
try {
//It is possible that the there will be a put in between these two gets. If so that shouldn't be a problem
//because we will always put the same value at the same key so our input streams will still represent
//the same data
final DiskLruCache.Value value = getDiskCache().get(safeKey);
if (value != null) {
result = value.getFile(0);
}
} catch (IOException e) {
if (Log.isLoggable(TAG, Log.WARN)) {
Log.w(TAG, "Unable to get from disk cache", e);
}
}
return result;
}
@Override
public void put(Key key, Writer writer) {
String safeKey = safeKeyGenerator.getSafeKey(key);
writeLocker.acquire(key);
try {
DiskLruCache.Editor editor = getDiskCache().edit(safeKey);
// Editor will be null if there are two concurrent puts. In the worst case we will just silently fail.
if (editor != null) {
try {
File file = editor.getFile(0);
if (writer.write(file)) {
editor.commit();
}
} finally {
editor.abortUnlessCommitted();
}
}
} catch (IOException e) {
if (Log.isLoggable(TAG, Log.WARN)) {
Log.w(TAG, "Unable to put to disk cache", e);
}
} finally {
writeLocker.release(key);
}
}
void release(Key key) {
WriteLock writeLock;
synchronized (this) {
writeLock = locks.get(key);
if (writeLock == null || writeLock.interestedThreads <= 0) {
throw new IllegalArgumentException(
"Cannot release a lock that is not held" + ", key: " + key + ", interestedThreads: "
+ (writeLock == null ? 0 : writeLock.interestedThreads));
}
if (--writeLock.interestedThreads == 0) {
WriteLock removed = locks.remove(key);
if (!removed.equals(writeLock)) {
throw new IllegalStateException("Removed the wrong lock"
+ ", expected to remove: " + writeLock
+ ", but actually removed: " + removed
+ ", key: " + key);
}
writeLockPool.offer(removed);
}
}
writeLock.lock.unlock();
}
public String getSafeKey(Key key) {
String safeKey;
synchronized (loadIdToSafeHash) {
safeKey = loadIdToSafeHash.get(key);
}
if (safeKey == null) {
try {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
key.updateDiskCacheKey(messageDigest);
safeKey = Util.sha256BytesToHex(messageDigest.digest());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
synchronized (loadIdToSafeHash) {
loadIdToSafeHash.put(key, safeKey);
}
}
return safeKey;
}
private void cache(String url, final Bitmap bitmap) {
Key key = new StringSignature(url);
// the key here is that Engine uses fetcher.getId() for constructing OriginalKey from EngineKey
// see Engine.load and also signature can be ignored because it is an EmptySignature instance for most
App.getInstance().getDiskCache().put(key, new Writer() {
@TargetApi(VERSION_CODES.KITKAT) // for try-with-resources
@Override public boolean write(File file) {
try (OutputStream out = new FileOutputStream(file)) {
// mimic default behavior you can also use Bitmap.compress
BitmapPool pool = Glide.get(getContext()).getBitmapPool();
BitmapResource resource = BitmapResource.obtain(bitmap, pool);
new BitmapEncoder().encode(resource, out);
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
});
}
@Override
public void onBindItemViewHolder(RecentPhotoViewHolder viewHolder, @NonNull Cursor cursor) {
viewHolder.imageView.setImageDrawable(null);
long id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns._ID));
long dateTaken = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.DATE_TAKEN));
long dateModified = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.DATE_MODIFIED));
String mimeType = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.MIME_TYPE));
int orientation = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.ORIENTATION));
final Uri uri = Uri.withAppendedPath(baseUri, Long.toString(id));
Key signature = new MediaStoreSignature(mimeType, dateModified, orientation);
GlideApp.with(getContext().getApplicationContext())
.load(uri)
.signature(signature)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(viewHolder.imageView);
viewHolder.imageView.setOnClickListener(v -> {
if (clickedListener != null) clickedListener.onItemClicked(uri);
});
}
@Override
public void onBindItemViewHolder(RecentPhotoViewHolder viewHolder, @NonNull Cursor cursor) {
viewHolder.imageView.setImageDrawable(null);
String path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.DATA));
long dateTaken = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.DATE_TAKEN));
long dateModified = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.DATE_MODIFIED));
String mimeType = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.MIME_TYPE));
String bucketId = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.BUCKET_ID));
int orientation = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.ORIENTATION));
long size = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.SIZE));
int width = cursor.getInt(cursor.getColumnIndexOrThrow(getWidthColumn(orientation)));
int height = cursor.getInt(cursor.getColumnIndexOrThrow(getHeightColumn(orientation)));
final Uri uri = Uri.fromFile(new File(path));
Key signature = new MediaStoreSignature(mimeType, dateModified, orientation);
GlideApp.with(getContext().getApplicationContext())
.load(uri)
.signature(signature)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.transition(DrawableTransitionOptions.withCrossFade())
.into(viewHolder.imageView);
viewHolder.imageView.setOnClickListener(v -> {
if (clickedListener != null) clickedListener.onItemClicked(uri, mimeType, bucketId, dateTaken, width, height, size);
});
}
/**
* Returns the signature {@link 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;
}
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;
this.decoder = decoder;
this.transformation = transformation;
this.encoder = encoder;
this.transcoder = transcoder;
this.sourceEncoder = sourceEncoder;
}
public EngineJob(Key key, ExecutorService diskCacheService, ExecutorService sourceService, boolean isCacheable,
EngineJobListener listener, EngineResourceFactory engineResourceFactory) {
this.key = key;
this.diskCacheService = diskCacheService;
this.sourceService = sourceService;
this.isCacheable = isCacheable;
this.listener = listener;
this.engineResourceFactory = engineResourceFactory;
}
Engine(MemoryCache cache, DiskCache.Factory diskCacheFactory, ExecutorService diskCacheService,
ExecutorService sourceService, Map<Key, EngineJob> jobs, EngineKeyFactory keyFactory,
Map<Key, WeakReference<EngineResource<?>>> activeResources, EngineJobFactory engineJobFactory,
ResourceRecycler resourceRecycler) {
this.cache = cache;
this.diskCacheProvider = new LazyDiskCacheProvider(diskCacheFactory);
if (activeResources == null) {
activeResources = new HashMap<Key, WeakReference<EngineResource<?>>>();
}
this.activeResources = activeResources;
if (keyFactory == null) {
keyFactory = new EngineKeyFactory();
}
this.keyFactory = keyFactory;
if (jobs == null) {
jobs = new HashMap<Key, EngineJob>();
}
this.jobs = jobs;
if (engineJobFactory == null) {
engineJobFactory = new EngineJobFactory(diskCacheService, sourceService, this);
}
this.engineJobFactory = engineJobFactory;
if (resourceRecycler == null) {
resourceRecycler = new ResourceRecycler();
}
this.resourceRecycler = resourceRecycler;
cache.setResourceRemovedListener(this);
}
private EngineResource<?> loadFromCache(Key key, boolean isMemoryCacheable) {
if (!isMemoryCacheable) {
return null;
}
EngineResource<?> cached = getEngineResourceFromCache(key);
if (cached != null) {
cached.acquire();
activeResources.put(key, new ResourceWeakReference(key, cached, getReferenceQueue()));
}
return cached;
}
@SuppressWarnings("unchecked")
private EngineResource<?> getEngineResourceFromCache(Key key) {
Resource<?> cached = cache.remove(key);
final EngineResource result;
if (cached == null) {
result = null;
} else if (cached instanceof EngineResource) {
// Save an object allocation if we've cached an EngineResource (the typical case).
result = (EngineResource) cached;
} else {
result = new EngineResource(cached, true /*isCacheable*/);
}
return result;
}
@SuppressWarnings("unchecked")
@Override
public void onEngineJobComplete(Key key, EngineResource<?> resource) {
Util.assertMainThread();
// A null resource indicates that the load failed, usually due to an exception.
if (resource != null) {
resource.setResourceListener(key, this);
if (resource.isCacheable()) {
activeResources.put(key, new ResourceWeakReference(key, resource, getReferenceQueue()));
}
}
// TODO: should this check that the engine job is still current?
jobs.remove(key);
}
@Override
public void onEngineJobCancelled(EngineJob engineJob, Key key) {
Util.assertMainThread();
EngineJob current = jobs.get(key);
if (engineJob.equals(current)) {
jobs.remove(key);
}
}
@Override
public void onResourceReleased(Key cacheKey, EngineResource resource) {
Util.assertMainThread();
activeResources.remove(cacheKey);
if (resource.isCacheable()) {
cache.put(cacheKey, resource);
} else {
resourceRecycler.recycle(resource);
}
}
@SuppressWarnings("rawtypes")
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, signature, width, height, cacheDecoder, sourceDecoder, transformation, encoder,
transcoder, sourceEncoder);
}
@Override
public void delete(Key key) {
String safeKey = safeKeyGenerator.getSafeKey(key);
try {
getDiskCache().remove(safeKey);
} catch (IOException e) {
if (Log.isLoggable(TAG, Log.WARN)) {
Log.w(TAG, "Unable to delete from disk cache", e);
}
}
}
void acquire(Key key) {
WriteLock writeLock;
synchronized (this) {
writeLock = locks.get(key);
if (writeLock == null) {
writeLock = writeLockPool.obtain();
locks.put(key, writeLock);
}
writeLock.interestedThreads++;
}
writeLock.lock.lock();
}
/**
* Create a full size drawable request for a given width and height that is
* as large as we can reasonably load into a view without causing massive
* jank problems or blank frames due to overly large textures.
*/
public final DrawableRequestBuilder<Uri> loadFull(Uri uri, Key key, Size original)
{
Size size = clampSize(original, MAXIMUM_FULL_RES_PIXELS, getMaxImageDisplaySize());
return mLargeImageBuilder
.clone()
.load(uri)
.signature(key)
.override(size.width(), size.height());
}
/**
* Create a full size drawable request for a given width and height that is
* smaller than loadFull, but is intended be large enough to fill the screen
* pixels.
*/
public DrawableRequestBuilder<Uri> loadScreen(Uri uri, Key key, Size original)
{
Size size = clampSize(original, MAXIMUM_SMOOTH_PIXELS, getMaxImageDisplaySize());
return mLargeImageBuilder
.clone()
.load(uri)
.signature(key)
.override(size.width(), size.height());
}
/**
* Create a small thumbnail sized image that has the same bounds as the
* media store thumbnail images.
* <p>
* If the Uri points at an animated gif, the gif will not play.
*/
public GenericRequestBuilder<Uri, ?, ?, GlideDrawable> loadMediaStoreThumb(Uri uri, Key key)
{
Size size = clampSize(MEDIASTORE_THUMB_SIZE, MAXIMUM_SMOOTH_PIXELS, getMaxImageDisplaySize());
return mTinyImageBuilder
.clone()
.load(uri)
.signature(key)
// This attempts to ensure we load the cached media store version.
.override(size.width(), size.height());
}
/**
* Create very tiny thumbnail request that should complete as fast
* as possible.
* <p>
* If the Uri points at an animated gif, the gif will not play.
*/
public GenericRequestBuilder<Uri, ?, ?, GlideDrawable> loadTinyThumb(Uri uri, Key key)
{
Size size = clampSize(TINY_THUMB_SIZE, MAXIMUM_SMOOTH_PIXELS, getMaxImageDisplaySize());
return mTinyImageBuilder
.clone()
.load(uri)
.signature(key)
.override(size.width(), size.height());
}
protected final Key generateSignature(FilmstripItemData data)
{
// Per Glide docs, make default mime type be the empty String
String mimeType = (data.getMimeType() == null) ? "" : data.getMimeType();
long modTimeSeconds = (data.getLastModifiedDate() == null) ? 0 :
data.getLastModifiedDate().getTime() / 1000;
return new MediaStoreSignature(mimeType, modTimeSeconds, data.getOrientation());
}
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,
float sizeMultiplier,
Drawable placeholderDrawable,
int placeholderResourceId,
Drawable errorDrawable,
int errorResourceId,
Drawable fallbackDrawable,
int fallbackResourceId,
RequestListener<? super A, R> requestListener,
RequestCoordinator requestCoordinator,
Engine engine,
Transformation<Z> transformation,
Class<R> transcodeClass,
boolean isMemoryCacheable,
GlideAnimationFactory<R> animationFactory,
int overrideWidth,
int overrideHeight,
DiskCacheStrategy diskCacheStrategy) {
@SuppressWarnings("unchecked")
GenericRequest<A, T, Z, R> request = (GenericRequest<A, T, Z, R>) REQUEST_POOL.poll();
if (request == null) {
request = new GenericRequest<A, T, Z, R>();
}
request.init(loadProvider,
model,
signature,
context,
priority,
target,
sizeMultiplier,
placeholderDrawable,
placeholderResourceId,
errorDrawable,
errorResourceId,
fallbackDrawable,
fallbackResourceId,
requestListener,
requestCoordinator,
engine,
transformation,
transcodeClass,
isMemoryCacheable,
animationFactory,
overrideWidth,
overrideHeight,
diskCacheStrategy);
return request;
}
private void init(
LoadProvider<A, T, Z, R> loadProvider,
A model,
Key signature,
Context context,
Priority priority,
Target<R> target,
float sizeMultiplier,
Drawable placeholderDrawable,
int placeholderResourceId,
Drawable errorDrawable,
int errorResourceId,
Drawable fallbackDrawable,
int fallbackResourceId,
RequestListener<? super A, R> requestListener,
RequestCoordinator requestCoordinator,
Engine engine,
Transformation<Z> transformation,
Class<R> transcodeClass,
boolean isMemoryCacheable,
GlideAnimationFactory<R> animationFactory,
int overrideWidth,
int overrideHeight,
DiskCacheStrategy diskCacheStrategy) {
this.loadProvider = loadProvider;
this.model = model;
this.signature = signature;
this.fallbackDrawable = fallbackDrawable;
this.fallbackResourceId = fallbackResourceId;
this.context = context.getApplicationContext();
this.priority = priority;
this.target = target;
this.sizeMultiplier = sizeMultiplier;
this.placeholderDrawable = placeholderDrawable;
this.placeholderResourceId = placeholderResourceId;
this.errorDrawable = errorDrawable;
this.errorResourceId = errorResourceId;
this.requestListener = requestListener;
this.requestCoordinator = requestCoordinator;
this.engine = engine;
this.transformation = transformation;
this.transcodeClass = transcodeClass;
this.isMemoryCacheable = isMemoryCacheable;
this.animationFactory = animationFactory;
this.overrideWidth = overrideWidth;
this.overrideHeight = overrideHeight;
this.diskCacheStrategy = diskCacheStrategy;
status = Status.PENDING;
// We allow null models by just setting an error drawable. Null models will always have empty providers, we
// simply skip our sanity checks in that unusual case.
if (model != null) {
check("ModelLoader", loadProvider.getModelLoader(), "try .using(ModelLoader)");
check("Transcoder", loadProvider.getTranscoder(), "try .as*(Class).transcode(ResourceTranscoder)");
check("Transformation", transformation, "try .transform(UnitTransformation.get())");
if (diskCacheStrategy.cacheSource()) {
check("SourceEncoder", loadProvider.getSourceEncoder(),
"try .sourceEncoder(Encoder) or .diskCacheStrategy(NONE/RESULT)");
} else {
check("SourceDecoder", loadProvider.getSourceDecoder(),
"try .decoder/.imageDecoder/.videoDecoder(ResourceDecoder) or .diskCacheStrategy(ALL/SOURCE)");
}
if (diskCacheStrategy.cacheSource() || diskCacheStrategy.cacheResult()) {
// TODO if(resourceClass.isAssignableFrom(InputStream.class) it is possible to wrap sourceDecoder
// and use it instead of cacheDecoder: new FileToStreamDecoder<Z>(sourceDecoder)
// in that case this shouldn't throw
check("CacheDecoder", loadProvider.getCacheDecoder(),
"try .cacheDecoder(ResouceDecoder) or .diskCacheStrategy(NONE)");
}
if (diskCacheStrategy.cacheResult()) {
check("Encoder", loadProvider.getEncoder(),
"try .encode(ResourceEncoder) or .diskCacheStrategy(NONE/SOURCE)");
}
}
}