上一篇文章從源碼角度深刻理解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); 複製代碼