上一篇文章從源碼角度深刻理解Glide(上)中,咱們已經把Glide加載圖片的基本流程走了一遍,想必你已經對Glide的加載原理有了新的認識而且見識到了Glide源碼的複雜邏輯,在咱們感嘆Glide源碼複雜的同時咱們也忽略了Glide加載圖片過程的其它細節,特別是緩存方面,咱們在上一篇文章中對於緩存的處理都是跳過的,這一篇文章咱們就從Glide的緩存開始再次對Glide進行深刻理解。html
Glide加載默認狀況下能夠分爲三級緩存,哪三級呢?他們分別是內存、磁盤和網絡。git
默認狀況下,Glide 會在開始一個新的圖片請求以前檢查如下多級的緩存:github
網絡級別的加載咱們已經在上一篇文章瞭解了,上面列出的前兩種狀況則是內存緩存,後兩種狀況則是磁盤緩存,若是以上四種狀況都不存在,Glide則會經過返回到原始資源以取回數據(原始文件,Uri, Url(網絡)等)算法
/**Key 接口*/
public interface Key {
String STRING_CHARSET_NAME = "UTF-8";
Charset CHARSET = Charset.forName(STRING_CHARSET_NAME);
void updateDiskCacheKey(@NonNull MessageDigest messageDigest);
@Override
boolean equals(Object o);
@Override
int hashCode();
}
複製代碼
private final EngineKeyFactory keyFactory;
/**Engine類的load方法*/
public <R> LoadStatus load(GlideContext glideContext,Object model, Key signature,int width,int height,Class<?> resourceClass,Class<R> transcodeClass,Priority priority,DiskCacheStrategy diskCacheStrategy,Map<Class<?>, Transformation<?>> transformations,boolean isTransformationRequired,boolean isScaleOnlyOrNoTransform, Options options,boolean isMemoryCacheable,boolean useUnlimitedSourceExecutorPool,boolean useAnimationPool,boolean onlyRetrieveFromCache,ResourceCallback cb) {
Util.assertMainThread();
long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0;
EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations,
resourceClass, transcodeClass, options);
//省略部分代碼
..........
}
/**EngineKey類*/
class EngineKey implements Key {
private final Object model;
private final int width;
private final int height;
private final Class<?> resourceClass;
private final Class<?> transcodeClass;
private final Key signature;
private final Map<Class<?>, Transformation<?>> transformations;
private final Options options;
private int hashCode;
EngineKey(
Object model,
Key signature,
int width,
int height,
Map<Class<?>, Transformation<?>> transformations,
Class<?> resourceClass,
Class<?> transcodeClass,
Options options) {
this.model = Preconditions.checkNotNull(model);
this.signature = Preconditions.checkNotNull(signature, "Signature must not be null");
this.width = width;
this.height = height;
this.transformations = Preconditions.checkNotNull(transformations);
this.resourceClass =
Preconditions.checkNotNull(resourceClass, "Resource class must not be null");
this.transcodeClass =
Preconditions.checkNotNull(transcodeClass, "Transcode class must not be null");
this.options = Preconditions.checkNotNull(options);
}
@Override
public boolean equals(Object o) {
if (o instanceof EngineKey) {
EngineKey other = (EngineKey) o;
return model.equals(other.model)
&& signature.equals(other.signature)
&& height == other.height
&& width == other.width
&& transformations.equals(other.transformations)
&& resourceClass.equals(other.resourceClass)
&& transcodeClass.equals(other.transcodeClass)
&& options.equals(other.options);
}
return false;
}
@Override
public int hashCode() {
if (hashCode == 0) {
hashCode = model.hashCode();
hashCode = 31 * hashCode + signature.hashCode();
hashCode = 31 * hashCode + width;
hashCode = 31 * hashCode + height;
hashCode = 31 * hashCode + transformations.hashCode();
hashCode = 31 * hashCode + resourceClass.hashCode();
hashCode = 31 * hashCode + transcodeClass.hashCode();
hashCode = 31 * hashCode + options.hashCode();
}
return hashCode;
}
}
複製代碼
//跳過內存緩存
RequestOptions requestOptions =new RequestOptions().skipMemoryCache(true);
Glide.with(this).load(IMAGE_URL).apply(requestOptions).into(imageView);
//Generated API 方式
GlideApp.with(this).load(IMAGE_URL).skipMemoryCache(true).into(imageView);
//清除內存緩存,必須在主線程中調用
Glide.get(context).clearMemory();
複製代碼
/**Engine類的load方法*/
public <R> LoadStatus load(GlideContext glideContext,Object model, Key signature,int width,int height,Class<?> resourceClass,Class<R> transcodeClass,Priority priority,DiskCacheStrategy diskCacheStrategy,Map<Class<?>, Transformation<?>> transformations,boolean isTransformationRequired,boolean isScaleOnlyOrNoTransform, Options options,boolean isMemoryCacheable,boolean useUnlimitedSourceExecutorPool,boolean useAnimationPool,boolean onlyRetrieveFromCache,ResourceCallback cb) {
//省略部分代碼
..........
EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
if (active != null) {
cb.onResourceReady(active, DataSource.MEMORY_CACHE);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Loaded resource from active resources", startTime, key);
}
return null;
}
//省略部分代碼
..........
}
複製代碼
private final ActiveResources activeResources;
/**Engine類的loadFromActiveResources方法*/
@Nullable
private EngineResource<?> loadFromActiveResources(Key key, boolean isMemoryCacheable) {
if (!isMemoryCacheable) {
return null;
}
EngineResource<?> active = activeResources.get(key);
if (active != null) {
active.acquire();
}
return active;
}
/**ActiveResources類*/
final class ActiveResources {
@VisibleForTesting
final Map<Key, ResourceWeakReference> activeEngineResources = new HashMap<>();
//省略部分代碼
........
@VisibleForTesting
static final class ResourceWeakReference extends WeakReference<EngineResource<?>> {
//省略部分代碼
........
}
}
/**Engine類的onEngineJobComplete方法*/
@SuppressWarnings("unchecked")
@Override
public void onEngineJobComplete(EngineJob<?> engineJob, 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.activate(key, resource);
}
}
jobs.removeIfCurrent(key, engineJob);
}
/**RequestOptions類的skipMemoryCache方法*/
public RequestOptions skipMemoryCache(boolean skip) {
if (isAutoCloneEnabled) {
return clone().skipMemoryCache(true);
}
this.isCacheable = !skip;
fields |= IS_CACHEABLE;
return selfOrThrowIfLocked();
}
複製代碼
/**Engine類的load方法*/
public <R> LoadStatus load(GlideContext glideContext,Object model, Key signature,int width,int height,Class<?> resourceClass,Class<R> transcodeClass,Priority priority,DiskCacheStrategy diskCacheStrategy,Map<Class<?>, Transformation<?>> transformations,boolean isTransformationRequired,boolean isScaleOnlyOrNoTransform, Options options,boolean isMemoryCacheable,boolean useUnlimitedSourceExecutorPool,boolean useAnimationPool,boolean onlyRetrieveFromCache,ResourceCallback cb) {
//省略部分代碼
..........
EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
if (cached != null) {
cb.onResourceReady(cached, DataSource.MEMORY_CACHE);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Loaded resource from cache", startTime, key);
}
return null;
}
//省略部分代碼
..........
}
/**Engine類的loadFromCache方法*/
private EngineResource<?> loadFromCache(Key key, boolean isMemoryCacheable) {
if (!isMemoryCacheable) {
return null;
}
EngineResource<?> cached = getEngineResourceFromCache(key);
if (cached != null) {
cached.acquire();
activeResources.activate(key, cached);
}
return cached;
}
/**Engine類的getEngineResourceFromCache方法*/
private final MemoryCache cache;
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 /*isMemoryCacheable*/, true /*isRecyclable*/); } return result; } /**GlideBuilder類的build方法*/ private MemoryCache cache; @NonNull Glide build(@NonNull Context context) { //省略部分代碼 .......... if (memoryCache == null) { memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize()); } if (diskCacheFactory == null) { diskCacheFactory = new InternalCacheDiskCacheFactory(context); } if (engine == null) { engine = new Engine( memoryCache, diskCacheFactory, diskCacheExecutor, sourceExecutor, GlideExecutor.newUnlimitedSourceExecutor(), GlideExecutor.newAnimationExecutor(), isActiveResourceRetentionAllowed); } //省略部分代碼 .......... } /**LruResourceCache類的實現繼承關係*/ public class LruResourceCache extends LruCache<Key, Resource<?>> implements MemoryCache{......} 複製代碼
/**EngineJob類的handleResultOnMainThread方法*/
@Synthetic
void handleResultOnMainThread() {
//省略部分代碼
..........
engineResource = engineResourceFactory.build(resource, isCacheable);
hasResource = true;
//省略部分代碼
..........
engineResource.acquire();
listener.onEngineJobComplete(this, key, engineResource);
engineResource.release();
//省略部分代碼
..........
}
/**EngineJob類的EngineResourceFactory內部類*/
@VisibleForTesting
static class EngineResourceFactory {
public <R> EngineResource<R> build(Resource<R> resource, boolean isMemoryCacheable) {
return new EngineResource<>(resource, isMemoryCacheable, /*isRecyclable=*/ true);
}
}
/**Engine類的onEngineJobComplete方法*/
@SuppressWarnings("unchecked")
@Override
public void onEngineJobComplete(EngineJob<?> engineJob, Key key, EngineResource<?> resource) {
//省略部分代碼
..........
if (resource != null) {
resource.setResourceListener(key, this);
if (resource.isCacheable()) {
activeResources.activate(key, resource);
}
}
//省略部分代碼
..........
}
複製代碼
/**EngineResource類的acquire方法*/
void acquire() {
if (isRecycled) {
throw new IllegalStateException("Cannot acquire a recycled resource");
}
if (!Looper.getMainLooper().equals(Looper.myLooper())) {
throw new IllegalThreadStateException("Must call acquire on the main thread");
}
++acquired;
}
/**EngineResource類的release方法*/
void release() {
if (acquired <= 0) {
throw new IllegalStateException("Cannot release a recycled or not yet acquired resource");
}
if (!Looper.getMainLooper().equals(Looper.myLooper())) {
throw new IllegalThreadStateException("Must call release on the main thread");
}
if (--acquired == 0) {
listener.onResourceReleased(key, this);
}
}
/**Engine類的onResourceReleased方法*/
@Override
public void onResourceReleased(Key cacheKey, EngineResource<?> resource) {
Util.assertMainThread();
activeResources.deactivate(cacheKey);
if (resource.isCacheable()) {
cache.put(cacheKey, resource);
} else {
resourceRecycler.recycle(resource);
}
}
複製代碼
RequestOptions requestOptions = new RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.NONE);//不使用緩存
Glide.with(Context).load(IMAGE_URL).apply(requestOptions).into(mImageView);
複製代碼
/**DecodeJob類的start方法*/
public void start(DecodeJob<R> decodeJob) {
this.decodeJob = decodeJob;
GlideExecutor executor = decodeJob.willDecodeFromCache()
? diskCacheExecutor
: getActiveSourceExecutor();
executor.execute(decodeJob);
}
/**DecodeJob類的willDecodeFromCache方法*/
boolean willDecodeFromCache() {
Stage firstStage = getNextStage(Stage.INITIALIZE);
return firstStage == Stage.RESOURCE_CACHE || firstStage == Stage.DATA_CACHE;
}
/**DecodeJob類的getNextStage方法*/
private Stage getNextStage(Stage current) {
switch (current) {
case INITIALIZE:
return diskCacheStrategy.decodeCachedResource()
? Stage.RESOURCE_CACHE : getNextStage(Stage.RESOURCE_CACHE);
case RESOURCE_CACHE:
return diskCacheStrategy.decodeCachedData()
? Stage.DATA_CACHE : getNextStage(Stage.DATA_CACHE);
case DATA_CACHE:
return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;
//省略部分代碼
......
}
}
/**DiskCacheStrategy類的ALL對象*/
public static final DiskCacheStrategy ALL = new DiskCacheStrategy() {
@Override
public boolean isDataCacheable(DataSource dataSource) {
return dataSource == DataSource.REMOTE;
}
@Override
public boolean isResourceCacheable(boolean isFromAlternateCacheKey, DataSource dataSource,
EncodeStrategy encodeStrategy) {
return dataSource != DataSource.RESOURCE_DISK_CACHE && dataSource != DataSource.MEMORY_CACHE;
}
@Override
public boolean decodeCachedResource() {
return true;
}
@Override
public boolean decodeCachedData() {
return true;
}
};
/**GlideBuilder類的build方法*/
@NonNull
Glide build(@NonNull Context context) {
//省略部分代碼
......
if (diskCacheExecutor == null) {
diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
}
//省略部分代碼
......
}
/**GlideExecutor類的newDiskCacheExecutor方法*/
private static final int DEFAULT_DISK_CACHE_EXECUTOR_THREADS = 1;
public static GlideExecutor newDiskCacheExecutor() {
return newDiskCacheExecutor(
DEFAULT_DISK_CACHE_EXECUTOR_THREADS,
DEFAULT_DISK_CACHE_EXECUTOR_NAME,
UncaughtThrowableStrategy.DEFAULT);
}
/**GlideExecutor類的newDiskCacheExecutor方法*/
public static GlideExecutor newDiskCacheExecutor(
int threadCount, String name, UncaughtThrowableStrategy uncaughtThrowableStrategy) {
return new GlideExecutor(
new ThreadPoolExecutor(
threadCount /* corePoolSize */,
threadCount /* maximumPoolSize */,
0 /* keepAliveTime */,
TimeUnit.MILLISECONDS,
new PriorityBlockingQueue<Runnable>(),
new DefaultThreadFactory(name, uncaughtThrowableStrategy, true)));
}
複製代碼
/**GlideBuilder類的build方法*/
private DiskCache.Factory diskCacheFactory;
@NonNull
Glide build(@NonNull Context context) {
//省略部分代碼
..........
if (diskCacheFactory == null) {
diskCacheFactory = new InternalCacheDiskCacheFactory(context);
}
//省略部分代碼
..........
}
/**InternalCacheDiskCacheFactory類的繼承關係*/
public final class InternalCacheDiskCacheFactory extends DiskLruCacheFactory {
//省略實現代碼
..........
}
/**DiskLruCacheFactory類的部分代碼*/
public class DiskLruCacheFactory implements DiskCache.Factory {
//省略部分代碼
..........
@Override
public DiskCache build() {
File cacheDir = cacheDirectoryGetter.getCacheDirectory();
//省略部分代碼
..........
return DiskLruCacheWrapper.create(cacheDir, diskCacheSize);
}
}
/**DiskLruCacheWrapper類的部分代碼*/
public class DiskLruCacheWrapper implements DiskCache {
//省略部分代碼
..........
private synchronized DiskLruCache getDiskCache() throws IOException {
if (diskLruCache == null) {
diskLruCache = DiskLruCache.open(directory, APP_VERSION, VALUE_COUNT, maxSize);
}
return diskLruCache;
}
//省略部分代碼
..........
}
/**DiskLruCache類的部分代碼*/
public final class DiskLruCache implements Closeable {
//省略部分代碼
..........
public static DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize)
throws IOException {
DiskLruCache cache = new DiskLruCache(directory, appVersion, valueCount, maxSize);
//省略部分代碼
..........
return cache;
}
//省略部分代碼
..........
}
複製代碼
/**DecodeJob的getNextGenerator方法*/
private DataFetcherGenerator getNextGenerator() {
switch (stage) {
case RESOURCE_CACHE:
return new ResourceCacheGenerator(decodeHelper, this);
case DATA_CACHE:
return new DataCacheGenerator(decodeHelper, this);
case SOURCE:
return new SourceGenerator(decodeHelper, this);
case FINISHED:
return null;
default:
throw new IllegalStateException("Unrecognized stage: " + stage);
}
}
複製代碼
/** ResourceCacheGenerator類的startNext方法*/
@SuppressWarnings("PMD.CollapsibleIfStatements")
@Override
public boolean startNext() {
//省略部分代碼
..........
currentKey =
new ResourceCacheKey(// NOPMD AvoidInstantiatingObjectsInLoops
helper.getArrayPool(),
sourceId,
helper.getSignature(),
helper.getWidth(),
helper.getHeight(),
transformation,
resourceClass,
helper.getOptions());
cacheFile = helper.getDiskCache().get(currentKey);
if (cacheFile != null) {
sourceKey = sourceId;
modelLoaders = helper.getModelLoaders(cacheFile);
modelLoaderIndex = 0;
}
}
loadData = null;
boolean started = false;
while (!started && hasNextModelLoader()) {
ModelLoader<File, ?> modelLoader = modelLoaders.get(modelLoaderIndex++);
loadData = modelLoader.buildLoadData(cacheFile,
helper.getWidth(), helper.getHeight(), helper.getOptions());
if (loadData != null && helper.hasLoadPath(loadData.fetcher.getDataClass())) {
started = true;
loadData.fetcher.loadData(helper.getPriority(), this);
}
}
return started;
}
/**DecodeHelper類的getDiskCache方法*/
DiskCache getDiskCache() {
return diskCacheProvider.getDiskCache();
}
/** LazyDiskCacheProvider類的getDiskCache方法 */
@Override
public DiskCache getDiskCache() {
if (diskCache == null) {
synchronized (this) {
if (diskCache == null) {
diskCache = factory.build();
}
if (diskCache == null) {
diskCache = new DiskCacheAdapter();
}
}
}
return diskCache;
}
複製代碼
/** ResourceCacheGenerator類的startNext方法*/
@Override
public void onDataReady(Object data) {
cb.onDataFetcherReady(sourceKey, data, loadData.fetcher, DataSource.RESOURCE_DISK_CACHE,
currentKey);
}
複製代碼
/** DataCacheGenerator類的startNext方法*/
@Override
public boolean startNext() {
//省略部分代碼
..........
Key originalKey = new DataCacheKey(sourceId, helper.getSignature());
cacheFile = helper.getDiskCache().get(originalKey);
if (cacheFile != null) {
this.sourceKey = sourceId;
modelLoaders = helper.getModelLoaders(cacheFile);
modelLoaderIndex = 0;
}
}
loadData = null;
boolean started = false;
while (!started && hasNextModelLoader()) {
ModelLoader<File, ?> modelLoader = modelLoaders.get(modelLoaderIndex++);
loadData =
modelLoader.buildLoadData(cacheFile, helper.getWidth(), helper.getHeight(),
helper.getOptions());
if (loadData != null && helper.hasLoadPath(loadData.fetcher.getDataClass())) {
started = true;
loadData.fetcher.loadData(helper.getPriority(), this);
}
}
return started;
}
/** DataCacheGenerator類的onDataReady方法*/
@Override
public void onDataReady(Object data) {
cb.onDataFetcherReady(sourceKey, data, loadData.fetcher, DataSource.DATA_DISK_CACHE, sourceKey);
}
複製代碼
/** DecodeJob類的decodeFromRetrievedData方法*/
private void decodeFromRetrievedData() {
//省略部分代碼
..........
notifyEncodeAndRelease(resource, currentDataSource);
//省略部分代碼
..........
}
/** DecodeJob類的notifyEncodeAndRelease方法*/
private final DeferredEncodeManager<?> deferredEncodeManager = new DeferredEncodeManager<>();
private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {
//省略部分代碼
..........
stage = Stage.ENCODE;
try {
if (deferredEncodeManager.hasResourceToEncode()) {
deferredEncodeManager.encode(diskCacheProvider, options);
}
}
//省略部分代碼
..........
}
/** DeferredEncodeManager類的encode方法**/
void encode(DiskCacheProvider diskCacheProvider, Options options) {
GlideTrace.beginSection("DecodeJob.encode");
try {
diskCacheProvider.getDiskCache().put(key,
new DataCacheWriter<>(encoder, toEncode, options));
} finally {
toEncode.unlock();
GlideTrace.endSection();
}
}
複製代碼
/**SourceGenerator類的onDataReady方法**/
private Object dataToCache;
@Override
public void onDataReady(Object data) {
DiskCacheStrategy diskCacheStrategy = helper.getDiskCacheStrategy();
if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) {
dataToCache = data;
cb.reschedule();
} else {
cb.onDataFetcherReady(loadData.sourceKey, data, loadData.fetcher,
loadData.fetcher.getDataSource(), originalKey);
}
}
/**SourceGenerator類的startNext方法**/
@Override
public boolean startNext() {
if (dataToCache != null) {
Object data = dataToCache;
dataToCache = null;
cacheData(data);
}
if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {
return true;
}
//省略部分代碼
..........
}
/**SourceGenerator類的cacheData方法**/
private void cacheData(Object dataToCache) {
long startTime = LogTime.getLogTime();
try {
Encoder<Object> encoder = helper.getSourceEncoder(dataToCache);
DataCacheWriter<Object> writer =
new DataCacheWriter<>(encoder, dataToCache, helper.getOptions());
originalKey = new DataCacheKey(loadData.sourceKey, helper.getSignature());
helper.getDiskCache().put(originalKey, writer);
}
//省略部分代碼
..........
sourceCacheGenerator =
new DataCacheGenerator(Collections.singletonList(loadData.sourceKey), helper, this);
}
/**DecodeJob類的reschedule方法**/
@Override
public void reschedule() {
runReason = RunReason.SWITCH_TO_SOURCE_SERVICE;
callback.reschedule(this);
}
/**Engine類的reschedule方法**/
@Override
public void reschedule(DecodeJob<?> job) {
getActiveSourceExecutor().execute(job);
}
複製代碼
RequestOptions requestOptions = new RequestOptions().onlyRetrieveFromCache(true);
Glide.with(this).load(IMAGE_URL).apply(requestOptions).into(mImageView);
//Generated API 方式
GlideApp.with(this)
.load(url)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(mImageView);
複製代碼
/**DecodeJob類的getNextStage方法**/
private Stage getNextStage(Stage current) {
switch (current) {
//省略部分代碼
..........
case DATA_CACHE:
return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;
case SOURCE:
case FINISHED:
return Stage.FINISHED;
}
}
/**DecodeJob類的getNextGenerator方法**/
private DataFetcherGenerator getNextGenerator() {
switch (stage) {
//省略部分代碼
..........
case FINISHED:
return null;
default:
throw new IllegalStateException("Unrecognized stage: " + stage);
}
}
複製代碼
/**SingleRequest類的onResourceReady方法**/
@Nullable
private List<RequestListener<R>> requestListeners;
private void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {
//省略部分代碼
..........
isCallingCallbacks = true;
try {
boolean anyListenerHandledUpdatingTarget = false;
//省略部分代碼
..........
if (!anyListenerHandledUpdatingTarget) {
Transition<? super R> animation =
animationFactory.build(dataSource, isFirstResource);
target.onResourceReady(result, animation);
}
}
//省略部分代碼
..........
}
/**Target 接口**/
public interface Target<R> extends LifecycleListener {}
/**ImageViewTarget類的onResourceReady方法**/
@Override
public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {
if (transition == null || !transition.transition(resource, this)) {
setResourceInternal(resource);
} else {
maybeUpdateAnimatable(resource);
}
}
/**ImageViewTarget類的setResourceInternal方法**/
private void setResourceInternal(@Nullable Z resource) {
setResource(resource);
maybeUpdateAnimatable(resource);
}
DrawableImageViewTarget
/**DrawableImageViewTarget類的setResource方法**/
@Override
protected void setResource(@Nullable Drawable resource) {
view.setImageDrawable(resource);
}
複製代碼
Glide.with(this).load(IMAGE_URL).listener(new RequestListener<Drawable>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
return false;
}
}).into(mImageView);
複製代碼
/**RequestBuilder類的listener方法**/
@Nullable
private List<RequestListener<TranscodeType>> requestListeners;
public RequestBuilder<TranscodeType> listener(
@Nullable RequestListener<TranscodeType> requestListener) {
this.requestListeners = null;
return addListener(requestListener);
}
/**RequestBuilder類的addListener方法**/
public RequestBuilder<TranscodeType> addListener(
@Nullable RequestListener<TranscodeType> requestListener) {
if (requestListener != null) {
if (this.requestListeners == null) {
this.requestListeners = new ArrayList<>();
}
this.requestListeners.add(requestListener);
}
return this;
}
/**SingleRequest類的onResourceReady方法**/
@Nullable
private List<RequestListener<R>> requestListeners;
private void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {
//省略部分代碼
..........
isCallingCallbacks = true;
try {
boolean anyListenerHandledUpdatingTarget = false;
if (requestListeners != null) {
for (RequestListener<R> listener : requestListeners) {
anyListenerHandledUpdatingTarget |=
listener.onResourceReady(result, model, target, dataSource, isFirstResource);
}
}
anyListenerHandledUpdatingTarget |=
targetListener != null
&& targetListener.onResourceReady(result, model, target, dataSource, isFirstResource);
if (!anyListenerHandledUpdatingTarget) {
Transition<? super R> animation =
animationFactory.build(dataSource, isFirstResource);
target.onResourceReady(result, animation);
}
}
//省略部分代碼
..........
}
複製代碼
//注意須要指定Glide的加載類型asBitmap,不指定Target不知道自己是是類型的Target
Glide.with(this).asBitmap().load(IMAGE_URL).into(new SimpleTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
//加載完成已經在主線程
mImageView.setImageBitmap(resource);
}
});
複製代碼
/**
* @author maoqitian
* @Description: 自定義RelativeLayout
* @date 2019/2/18 0018 19:51
*/
public class MyView extends RelativeLayout {
private ViewTarget<MyView, Drawable> viewTarget;
public MyView(Context context) {
super(context);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
viewTarget =new ViewTarget<MyView, Drawable>(this) {
@Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
setBackground(resource);
}
};
}
public ViewTarget<MyView, Drawable> getViewTarget() {
return viewTarget;
}
}
//使用Glide加載
MyView rl_view = findViewById(R.id.rl_view);
Glide.with(this).load(IMAGE_URL).into(rl_view.getViewTarget());
複製代碼
new Thread(new Runnable() {
@Override
public void run() {
FutureTarget<File> target = null;
RequestManager requestManager = Glide.with(MainActivity.this);
try {
target = requestManager
.downloadOnly()
.load(IMAGE_URL)
.submit();
final File downloadedFile = target.get();
Log.i(TAG,"緩存文件路徑"+downloadedFile.getAbsolutePath());
} catch (ExecutionException | InterruptedException e) {
} finally {
if (target != null) {
target.cancel(true); // mayInterruptIfRunning
}
}
}
}).start();
複製代碼
Glide.with(this).load(IMAGE_URL).preload();
複製代碼
/**RequestBuilder類的preload方法**/
@NonNull
public Target<TranscodeType> preload() {
return preload(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL);
}
/**RequestBuilder類的preload方法**/
@NonNull
public Target<TranscodeType> preload(int width, int height) {
final PreloadTarget<TranscodeType> target = PreloadTarget.obtain(requestManager, width, height);
return into(target);
}
/**RequestBuilder類的onResourceReady方法**/
public final class PreloadTarget<Z> extends SimpleTarget<Z> {
private static final Handler HANDLER = new Handler(Looper.getMainLooper(), new Callback() {
@Override
public boolean handleMessage(Message message) {
if (message.what == MESSAGE_CLEAR) {
((PreloadTarget<?>) message.obj).clear();
return true;
}
return false;
}
});
//省略部分代碼
..........
public static <Z> PreloadTarget<Z> obtain(RequestManager requestManager, int width, int height) {
return new PreloadTarget<>(requestManager, width, height);
}
@Override
public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {
HANDLER.obtainMessage(MESSAGE_CLEAR, this).sendToTarget();
}
//省略部分代碼
..........
}
複製代碼
//在app下的gradle添加Glide註解處理器的依賴
dependencies {
annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'
}
//新建一個類集成AppGlideModule並添加上@GlideModule註解,從新rebuild項目就可使用GlideApp了
@GlideModule
public final class MyAppGlideModule extends AppGlideModule {}
複製代碼
/**GlideApp類部分代碼**/
public final class GlideApp {
//省略部分代碼
..........
@NonNull
public static GlideRequests with(@NonNull Context context) {
return (GlideRequests) Glide.with(context);
}
//省略部分代碼
..........
}
/**GlideApp類部分代碼**/
public class GlideRequest<TranscodeType> extends RequestBuilder<TranscodeType> implements Cloneable {
//省略部分代碼
..........
@NonNull
@CheckResult
public GlideRequest<TranscodeType> placeholder(@Nullable Drawable drawable) {
if (getMutableOptions() instanceof GlideOptions) {
this.requestOptions = ((GlideOptions) getMutableOptions()).placeholder(drawable);
} else {
this.requestOptions = new GlideOptions().apply(this.requestOptions).placeholder(drawable);
}
return this;
}
//省略部分代碼
..........
}
/**RequestBuilder類的getMutableOptions方法**/
protected RequestOptions getMutableOptions() {
return defaultRequestOptions == this.requestOptions
? this.requestOptions.clone() : this.requestOptions;
}
複製代碼
/**
* @author maoqitian
* @Description: GlideApp 功能擴展類
* @date 2019/2/19 0019 12:51
*/
@GlideExtension
public class MyGlideExtension {
private MyGlideExtension() {
}
//能夠爲方法任意添加參數,但要保證第一個參數爲 RequestOptions
/**
* 設置通用的加載佔位圖和錯誤加載圖
* @param options
*/
@GlideOption
public static void normalPlaceholder(RequestOptions options) {
options.placeholder(R.drawable.ic_cloud_download_black_24dp).error(R.drawable.ic_error_black_24dp);
}
}
/**GlideOptions類中生成對應的方法**/
/**
* @see MyGlideExtension#normalPlaceholder(RequestOptions)
*/
@CheckResult
@NonNull
public GlideOptions normalPlaceholder() {
if (isAutoCloneEnabled()) {
return clone().normalPlaceholder();
}
MyGlideExtension.normalPlaceholder(this);
return this;
}
/**GlideRequest類中生成對應的方法**/
/**
* @see GlideOptions#normalPlaceholder()
*/
@CheckResult
@NonNull
public GlideRequest<TranscodeType> normalPlaceholder() {
if (getMutableOptions() instanceof GlideOptions) {
this.requestOptions = ((GlideOptions) getMutableOptions()).normalPlaceholder();
} else {
this.requestOptions = new GlideOptions().apply(this.requestOptions).normalPlaceholder();
}
return this;
}
複製代碼
//調用咱們剛剛設置的擴展功能方法
GlideApp.with(this).load(IMAGE_URL)
.normalPlaceholder()
.into(mImageView);
複製代碼
@GlideExtension
public class MyGlideExtension {
private static final RequestOptions DECODE_TYPE_GIF = decodeTypeOf(GifDrawable.class).lock();
@GlideType(GifDrawable.class)
public static void asMyGif(RequestBuilder<GifDrawable> requestBuilder) {
requestBuilder
.transition(new DrawableTransitionOptions())
.apply(DECODE_TYPE_GIF);
}
}
/**GlideRequests類中生成的asMyGif方法**/
/**
* @see MyGlideExtension#asMyGif(RequestBuilder)
*/
@NonNull
@CheckResult
public GlideRequest<GifDrawable> asMyGif() {
GlideRequest<GifDrawable> requestBuilder = this.as(GifDrawable.class);
MyGlideExtension.asMyGif(requestBuilder);
return requestBuilder;
}
複製代碼
GlideApp.with(this).asMyGif().load(IMAGE_URL)
.into(mImageView);
複製代碼