探索Android开源框架 - 4. Glide使用及源码解析
使用
1. 添加依赖
implementation 'com.github.bumptech.glide:glide:4.12.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'复制代码
2. 基础使用
加载图片
Glide.with(this) .load(imgUrl) .into(imageView1)复制代码
取消加载
Glide.with(this).clear(imageView1)复制代码
实际上,当 Glide.with() 中传入的 Activity 或 Fragment 实例销毁时,Glide 会自动取消加载并回收资源;
3. 进阶操作
更多的可选配置
Glide.with(this)//上下文对象Context .load(imgUrl)//图片地址 .placeholder(R.mipmap.ic_launcher)//加载前的占位图 .error(R.mipmap.ic_launcher)//加载失败的占位图 .override(150,100)//指定图片尺寸(一般不用设置,Glide会自动根据ImageView的大小来决定图片的大小) .skipMemoryCache(true)//跳过内存缓存 .diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)//根据图片资源智能地选择使用哪一种缓存策略(默认选项) .diskCacheStrategy(DiskCacheStrategy.ALL)//既缓存原始图片,也缓存转换过的图片 .diskCacheStrategy(DiskCacheStrategy.DATA)//只缓存原始图片 .diskCacheStrategy(DiskCacheStrategy.RESOURCE)//只缓存转换过的图片 .diskCacheStrategy(DiskCacheStrategy.NONE)//禁用磁盘缓存 .priority(Priority.HIGH)//优先级 .thumbnail( Glide.with(this).load(imgUrl).override(20) ) //设置缩略图 .thumbnail(0.25f)//压缩原图为缩略图 .into(ivGlide2)复制代码
更多的可选配置可以参考官方文档
通过 RequestOptions 共享配置
val options = RequestOptions() .placeholder(R.mipmap.ic_launcher) .error(R.mipmap.ic_launcher) Glide.with(this) .load(imgUrl) .apply(options) .into(imageView1) Glide.with(this) .load(imgUrl) .apply(options) .into(imageView2)复制代码
源码解析
源码方面主要从最基本的三个方法入手:with,load,into
1. with
Glide.with源码如下,根据不同上下文对象有多个重载方法,首先通过getRetriever方法获取RequestManagerRetriever对象,再通过get方法获取RequestManager实例
public static RequestManager with(@NonNull Context context) { return getRetriever(context).get(context); } public static RequestManager with(@NonNull Activity activity) { return getRetriever(activity).get(activity); } public static RequestManager with(@NonNull FragmentActivity activity) { return getRetriever(activity).get(activity); } public static RequestManager with(@NonNull Fragment fragment) { return getRetriever(fragment.getContext()).get(fragment); } public static RequestManager with(@NonNull android.app.Fragment fragment) { return getRetriever(fragment.getActivity()).get(fragment); } public static RequestManager with(@NonNull View view) { return getRetriever(view.getContext()).get(view); }复制代码
getRetriever方法中通过Glide.get通过懒汉式+双重校验锁获取Glide单例,再通过getter方法获取requestManagerRetriever属性;
private static RequestManagerRetriever getRetriever(@Nullable Context context) { Preconditions.checkNotNull( context, "You cannot start a load on a not yet attached View or a Fragment where getActivity() " + "returns null (which usually occurs when getActivity() is called before the Fragment " + "is attached or after the Fragment is destroyed)."); return Glide.get(context).getRequestManagerRetriever(); }复制代码
获取Glide实例
public static Glide get(@NonNull Context context) { if (glide == null) { GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules(context.getApplicationContext()); synchronized (Glide.class) { if (glide == null) { checkAndInitializeGlide(context, annotationGeneratedModule); } } } return glide; }复制代码
真正创建并初始化Glide实例实在initializeGlide方法, 调用GlideBuilder.build方法通过建造者模式创建Glide实例
private static void checkAndInitializeGlide( @NonNull Context context, @Nullable GeneratedAppGlideModule generatedAppGlideModule) { if (isInitializing) { throw new IllegalStateException( "You cannot call Glide.get() in registerComponents()," + " use the provided Glide instance instead"); } isInitializing = true; initializeGlide(context, generatedAppGlideModule); isInitializing = false; } private static void initializeGlide( @NonNull Context context, @Nullable GeneratedAppGlideModule generatedAppGlideModule) { initializeGlide(context, new GlideBuilder(), generatedAppGlideModule); } private static void initializeGlide( @NonNull Context context, @NonNull GlideBuilder builder, @Nullable GeneratedAppGlideModule annotationGeneratedModule) { Context applicationContext = context.getApplicationContext(); ... Glide glide = builder.build(applicationContext); ... Glide.glide = glide; }复制代码
GlideBuilder.build方法代码如下
Glide build(@NonNull Context context) { //获取图片的线程池 if (sourceExecutor == null) { sourceExecutor = GlideExecutor.newSourceExecutor(); } //磁盘缓存的线程池 if (diskCacheExecutor == null) { diskCacheExecutor = GlideExecutor.newDiskCacheExecutor(); } //动画的线程池 if (animationExecutor == null) { animationExecutor = GlideExecutor.newAnimationExecutor(); } //创建内存大小控制器 if (memorySizeCalculator == null) { memorySizeCalculator = new MemorySizeCalculator.Builder(context).build(); } //创建网络监听的工厂 if (connectivityMonitorFactory == null) { connectivityMonitorFactory = new DefaultConnectivityMonitorFactory(); } if (bitmapPool == null) { int size = memorySizeCalculator.getBitmapPoolSize(); if (size > 0) { // 使用缓存,则创建bitmap对象池 bitmapPool = new LruBitmapPool(size); } else { // 不使用缓存 bitmapPool = new BitmapPoolAdapter(); } } //创建对象数组缓存池 if (arrayPool == null) { arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes()); } //创建内存缓存 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(), animationExecutor, isActiveResourceRetentionAllowed); } if (defaultRequestListeners == null) { defaultRequestListeners = Collections.emptyList(); } else { defaultRequestListeners = Collections.unmodifiableList(defaultRequestListeners); } GlideExperiments experiments = glideExperimentsBuilder.build(); //创建请求管理类,其构造方法中会实例化一个主线程的handler对象,用于线程的切换 RequestManagerRetriever requestManagerRetriever = new RequestManagerRetriever(requestManagerFactory, experiments); return new Glide( context, engine, memoryCache, bitmapPool, arrayPool, requestManagerRetriever, connectivityMonitorFactory, logLevel, defaultRequestOptionsFactory, defaultTransitionOptions, defaultRequestListeners, experiments); }复制代码
上面代码中RequestManagerRetriever的构造方法如下
public RequestManagerRetriever( @Nullable RequestManagerFactory factory, GlideExperiments experiments) { this.factory = factory != null ? factory : DEFAULT_FACTORY; handler = new Handler(Looper.getMainLooper(), this /* Callback */); frameWaiter = buildFrameWaiter(experiments); }复制代码
RequestManagerRetriever.get
上面通过glide单例获取RequestManagerRetriever实例,下面再调用其get方法获取RequestManager实例,也是有多个重载方法
public RequestManager get(@NonNull Context context) { //context判空及实际类型判断 if (context == null) { throw new IllegalArgumentException("You cannot start a load on a null Context"); } else if (Util.isOnMainThread() && !(context instanceof Application)) { if (context instanceof FragmentActivity) { return get((FragmentActivity) context); } else if (context instanceof Activity) { return get((Activity) context); } else if (context instanceof ContextWrapper && ((ContextWrapper) context).getBaseContext().getApplicationContext() != null) { return get(((ContextWrapper) context).getBaseContext()); } } return getApplicationManager(context); } public RequestManager get(@NonNull FragmentActivity activity) { if (Util.isOnBackgroundThread()) { return get(activity.getApplicationContext()); } else { ... FragmentManager fm = activity.getSupportFragmentManager(); return supportFragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity)); } } public RequestManager get(@NonNull Fragment fragment) { ... if (Util.isOnBackgroundThread()) { return get(fragment.getContext().getApplicationContext()); } else { ... FragmentManager fm = fragment.getChildFragmentManager(); return supportFragmentGet(fragment.getContext(), fm, fragment, fragment.isVisible()); } } public RequestManager get(@NonNull Activity activity) { if (Util.isOnBackgroundThread()) { return get(activity.getApplicationContext()); } else if (activity instanceof FragmentActivity) { return get((FragmentActivity) activity); } else { ... android.app.FragmentManager fm = activity.getFragmentManager(); return fragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity)); } } public RequestManager get(@NonNull View view) { ... Activity activity = findActivity(view.getContext()); if (activity == null) { return get(view.getContext().getApplicationContext()); } if (activity instanceof FragmentActivity) { Fragment fragment = findSupportFragment(view, (FragmentActivity) activity); return fragment != null ? get(fragment) : get((FragmentActivity) activity); } android.app.Fragment fragment = findFragment(view, activity); if (fragment == null) { return get(activity); } return get(fragment); }复制代码
最终会调用supportFragmentGet或fragmentGet获取requestManager实例,其中会创建一个Fragment,那么我们就知道了glide是通过在内部维护一个fragment来管理生命周期的
private RequestManager supportFragmentGet( @NonNull Context context, @NonNull FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) { SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint); RequestManager requestManager = current.getRequestManager(); if (requestManager == null) { Glide glide = Glide.get(context); requestManager = factory.build( glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context); if (isParentVisible) { requestManager.onStart(); } current.setRequestManager(requestManager); } return requestManager; } private RequestManager fragmentGet( @NonNull Context context, @NonNull android.app.FragmentManager fm, @Nullable android.app.Fragment parentHint, boolean isParentVisible) { RequestManagerFragment current = getRequestManagerFragment(fm, parentHint); RequestManager requestManager = current.getRequestManager(); if (requestManager == null) { Glide glide = Glide.get(context); requestManager = factory.build( glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context); if (isParentVisible) { requestManager.onStart(); } current.setRequestManager(requestManager); } return requestManager; }复制代码
2. load
此时的load其实已经是RequestManager.load方法,也是有多个重载方法,可以传入不同的图片源
public RequestBuilder<Drawable> load(@Nullable Bitmap bitmap) { return asDrawable().load(bitmap); } public RequestBuilder<Drawable> load(@Nullable Drawable drawable) { return asDrawable().load(drawable); } public RequestBuilder<Drawable> load(@Nullable String string) { return asDrawable().load(string); } public RequestBuilder<Drawable> load(@Nullable Uri uri) { return asDrawable().load(uri); } public RequestBuilder<Drawable> load(@Nullable File file) { return asDrawable().load(file); } public RequestBuilder<Drawable> load(@RawRes @DrawableRes @Nullable Integer resourceId) { return asDrawable().load(resourceId); } public RequestBuilder<Drawable> load(@Nullable URL url) { return asDrawable().load(url); } public RequestBuilder<Drawable> load(@Nullable byte[] model) { return asDrawable().load(model); } public RequestBuilder<Drawable> load(@Nullable Object model) { return asDrawable().load(model); }复制代码
上面代码中都会先调用asDrawable(),那么我们先来看看他是个啥
asDrawable()
asDrawable代码如下,其中只是调用as方法并传入Drawable.class, 再看看as方法,原来是创建一个图片类型为Drawable类型的RequestBuilder请求
public RequestBuilder<Drawable> asDrawable() { return as(Drawable.class); } public <ResourceType> RequestBuilder<ResourceType> as( @NonNull Class<ResourceType> resourceClass) { return new RequestBuilder<>(glide, this, resourceClass, context); }复制代码
而且我们发现还要相似的asBitmap,asGif
public RequestBuilder<GifDrawable> asGif() { return as(GifDrawable.class).apply(DECODE_TYPE_GIF); } public RequestBuilder<Bitmap> asBitmap() { return as(Bitmap.class).apply(DECODE_TYPE_BITMAP); }复制代码
现在我们知道了RequestManager.load是通过获取RequestBuilder实例,再调用其load方法
RequestBuilder.load
RequestBuilder.load也是有多个重载方法,但其中都是调用loadGeneric方法
public RequestBuilder<TranscodeType> load(@Nullable String string) { return loadGeneric(string); } public RequestBuilder<TranscodeType> load(@Nullable Uri uri) { return loadGeneric(uri); } public RequestBuilder<TranscodeType> load(@Nullable File file) { return loadGeneric(file); } public RequestBuilder<TranscodeType> load(@Nullable Drawable drawable) { return loadGeneric(drawable).apply(diskCacheStrategyOf(DiskCacheStrategy.NONE)); } public RequestBuilder<TranscodeType> load(@Nullable Bitmap bitmap) { return loadGeneric(bitmap).apply(diskCacheStrategyOf(DiskCacheStrategy.NONE)); } public RequestBuilder<TranscodeType> load(@RawRes @DrawableRes @Nullable Integer resourceId) { return loadGeneric(resourceId).apply(signatureOf(AndroidResourceSignature.obtain(context))); }复制代码
loadGeneric代码如下,主要是将图片源保存起来,并设置是否设置了图片源的标识isModelSet = true,最后返回了RequestBuilder自身this
private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) { if (isAutoCloneEnabled()) { return clone().loadGeneric(model); } this.model = model; isModelSet = true; return selfOrThrowIfLocked(); } protected final T selfOrThrowIfLocked() { if (isLocked) { throw new IllegalStateException("You cannot modify locked T, consider clone()"); } return self(); } private T self() { return (T) this; }复制代码
3. into
接下来是通过RequestBuilder.into方法设置目标view
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) { Util.assertMainThread();//断言是在主线程调用的 Preconditions.checkNotNull(view);//非空判断 BaseRequestOptions<?> requestOptions = this; if (!requestOptions.isTransformationSet() && requestOptions.isTransformationAllowed() && view.getScaleType() != null) { //熟悉的ScaleType们 switch (view.getScaleType()) { case CENTER_CROP: requestOptions = requestOptions.clone().optionalCenterCrop(); break; case CENTER_INSIDE: requestOptions = requestOptions.clone().optionalCenterInside(); break; case FIT_CENTER: case FIT_START: case FIT_END: requestOptions = requestOptions.clone().optionalFitCenter(); break; case FIT_XY: requestOptions = requestOptions.clone().optionalCenterInside(); break; case CENTER: case MATRIX: default: // Do nothing. } } return into( glideContext.buildImageViewTarget(view, transcodeClass), /*targetListener=*/ null, requestOptions, Executors.mainThreadExecutor()); }复制代码
最终是将view通过buildImageViewTarget方法转为target,transcodeClass为Bitmap.class或Drawable.class
public <X> ViewTarget<ImageView, X> buildImageViewTarget( @NonNull ImageView imageView, @NonNull Class<X> transcodeClass) { return imageViewTargetFactory.buildTarget(imageView, transcodeClass); } public class ImageViewTargetFactory { @NonNull @SuppressWarnings("unchecked") public <Z> ViewTarget<ImageView, Z> buildTarget( @NonNull ImageView view, @NonNull Class<Z> clazz) { if (Bitmap.class.equals(clazz)) { return (ViewTarget<ImageView, Z>) new BitmapImageViewTarget(view); } else if (Drawable.class.isAssignableFrom(clazz)) { return (ViewTarget<ImageView, Z>) new DrawableImageViewTarget(view); } else { throw new IllegalArgumentException( "Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)"); } } }复制代码
入参为target的into方法中,有四个入参,分别为target,监听,配置信息,和线程池,其代码如下,
其中通过buildRequest创建一个请求
private <Y extends Target<TranscodeType>> Y into( @NonNull Y target, @Nullable RequestListener<TranscodeType> targetListener, BaseRequestOptions<?> options, Executor callbackExecutor) { Preconditions.checkNotNull(target); if (!isModelSet) { throw new IllegalArgumentException("You must call #load() before calling #into()"); } //创建request对象 Request request = buildRequest(target, targetListener, options, callbackExecutor); Request previous = target.getRequest(); if (request.isEquivalentTo(previous) && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) { if (!Preconditions.checkNotNull(previous).isRunning()) { previous.begin(); } return target; } //将target原先所关联的请求断开 requestManager.clear(target); //并设置为新的请求, target.setRequest(request); //然后通过requestManager.track()进行一些列的加载和处理显示操作 requestManager.track(target, request); return target; }复制代码
requestManager.track
track方法代码如下
synchronized void track(@NonNull Target<?> target, @NonNull Request request) { targetTracker.track(target); requestTracker.runRequest(request); } //将请求保存起来 public void track(@NonNull Target<?> target) { targets.add(target); } //如果当前不是暂停状态则调用begin方法处理请求,如果是暂停状态则加入到pendingRequests集合中 public void runRequest(@NonNull Request request) { requests.add(request); if (!isPaused) { request.begin(); } else { request.clear(); if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "Paused, delaying request"); } pendingRequests.add(request); } }复制代码
SingleRequest.begin
而通过跟踪buildRequest方法,发现到最后是调用SingleRequest.obtain创建Request实例,也就是Request的实现类是SingleRequest,那么来看一下SingleRequest的begin方法
public void begin() { synchronized (requestLock) { assertNotCallingCallbacks(); stateVerifier.throwIfRecycled(); startTime = LogTime.getLogTime(); ... status = Status.WAITING_FOR_SIZE; if (Util.isValidDimensions(overrideWidth, overrideHeight)) { //将目标view的宽高传入onSizeReady onSizeReady(overrideWidth, overrideHeight); } else { target.getSize(this); } if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE) && canNotifyStatusChanged()) { target.onLoadStarted(getPlaceholderDrawable()); } if (IS_VERBOSE_LOGGABLE) { logV("finished run method in " + LogTime.getElapsedMillis(startTime)); } } }复制代码
通过上面代码可以看出begin中最关键的一行是调用onSizeReady方法,并传入目标view的宽高,onSizeReady代码如下
public void onSizeReady(int width, int height) { stateVerifier.throwIfRecycled(); synchronized (requestLock) { ... if (status != Status.WAITING_FOR_SIZE) { return; } //修改status为running status = Status.RUNNING; float sizeMultiplier = requestOptions.getSizeMultiplier(); this.width = maybeApplySizeMultiplier(width, sizeMultiplier); this.height = maybeApplySizeMultiplier(height, sizeMultiplier); //调用Engine.load对请求进行处理 loadStatus = engine.load( glideContext, model, requestOptions.getSignature(), this.width, this.height, requestOptions.getResourceClass(), transcodeClass, priority, requestOptions.getDiskCacheStrategy(), requestOptions.getTransformations(), requestOptions.isTransformationRequired(), requestOptions.isScaleOnlyOrNoTransform(), requestOptions.getOptions(), requestOptions.isMemoryCacheable(), requestOptions.getUseUnlimitedSourceGeneratorsPool(), requestOptions.getUseAnimationPool(), requestOptions.getOnlyRetrieveFromCache(), this, callbackExecutor); if (status != Status.RUNNING) { loadStatus = null; } } }复制代码
Engine.load
可以看到上面onSizeReady主要是调用了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, Executor callbackExecutor) { long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0; EngineKey key = keyFactory.buildKey( model, signature, width, height, transformations, resourceClass, transcodeClass, options); EngineResource<?> memoryResource; synchronized (this) { //获取缓存中的图片资源 memoryResource = loadFromMemory(key, isMemoryCacheable, startTime); if (memoryResource == null) { //缓存中没有则等待或新开一个job获取图片资源 return waitForExistingOrStartNewJob( glideContext, model, signature, width, height, resourceClass, transcodeClass, priority, diskCacheStrategy, transformations, isTransformationRequired, isScaleOnlyOrNoTransform, options, isMemoryCacheable, useUnlimitedSourceExecutorPool, useAnimationPool, onlyRetrieveFromCache, cb, callbackExecutor, key, startTime); } } // Avoid calling back while holding the engine lock, doing so makes it easier for callers to // deadlock. cb.onResourceReady( memoryResource, DataSource.MEMORY_CACHE, /* isLoadedFromAlternateCacheKey= */ false); return null; }复制代码
Engine.load中主要是先通过loadFromMemory获取缓存中的图片资源,取不到则调用waitForExistingOrStartNewJob
Engine.loadFromMemory
loadFromMemory代码如下
private EngineResource<?> loadFromMemory( EngineKey key, boolean isMemoryCacheable, long startTime) { //判断是否允许内存缓存 if (!isMemoryCacheable) { return null; } //从ActiveResources中取 EngineResource<?> active = loadFromActiveResources(key); if (active != null) { return active; } //从lruCache中取 EngineResource<?> cached = loadFromCache(key); if (cached != null) { return cached; } return null; }复制代码
loadFromActiveResources
loadFromActiveResources代码如下,其中ActiveResources维护了一个value为弱引用的HashMap<Key, ResourceWeakReference>, 调用其get方法获取图片资源,如果取到则调用acquire对 对象的引用数量 进行加一操作,内存缓存是通过计数散列算法来进行相应的操作的,如果对象的计数树为0,则说明暂无其他对象引用此资源,那么此资源可以被释放了
private EngineResource<?> loadFromActiveResources(Key key) { EngineResource<?> active = activeResources.get(key); if (active != null) { active.acquire(); } return active; } private final ActiveResources activeResources; final class ActiveResources { private final boolean isActiveResourceRetentionAllowed; private final Executor monitorClearedResourcesExecutor; @VisibleForTesting final Map<Key, ResourceWeakReference> activeEngineResources = new HashMap<>(); private final ReferenceQueue<EngineResource<?>> resourceReferenceQueue = new ReferenceQueue<>(); private ResourceListener listener; private volatile boolean isShutdown; @Nullable private volatile DequeuedResourceCallback cb; ... synchronized void activate(Key key, EngineResource<?> resource) { ResourceWeakReference toPut = new ResourceWeakReference( key, resource, resourceReferenceQueue, isActiveResourceRetentionAllowed); ResourceWeakReference removed = activeEngineResources.put(key, toPut); if (removed != null) { removed.reset(); } } synchronized EngineResource<?> get(Key key) { ResourceWeakReference activeRef = activeEngineResources.get(key); if (activeRef == null) { return null; } EngineResource<?> active = activeRef.get(); if (active == null) { cleanupActiveReference(activeRef); } return active; } } class EngineResource<Z> implements Resource<Z> { ... private int acquired; private boolean isRecycled; ... synchronized void acquire() { if (isRecycled) { throw new IllegalStateException("Cannot acquire a recycled resource"); } ++acquired; } }复制代码
loadFromCache
继续回到loadFromMemory,如果ActiveResources中没有取到,则调用loadFromCache尝试从lruCache中取,loadFromCache代码如下,从lruCache中取图片资源,如果取到则调用acquire对 对象的引用数量 进行加一操作,并调用activeResources.activate添加到activeResources中
private EngineResource<?> loadFromCache(Key key) { EngineResource<?> cached = getEngineResourceFromCache(key); if (cached != null) { cached.acquire(); activeResources.activate(key, cached); } return cached; } private EngineResource<?> getEngineResourceFromCache(Key key) { // 对于Lru的数据获取是通过删除的方式来获取 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, /*isMemoryCacheable=*/ true, /*isRecyclable=*/ true, key, /*listener=*/ this); } return result; }复制代码
上面代码中的cache就是前面GlideBuilder.build中初始化的memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
LruResourceCache
LruResourceCache继承了LruCache,并实现MemoryCache接口,LruCache内部利用了LinkedHashMap accessOrder 等于true时会对内容按照访问的先后顺序排序,会把最近访问的元素放到双链表的尾部这样一个特性实现的,代码如下
public class LruResourceCache extends LruCache<Key, Resource<?>> implements MemoryCache { ... } public class LruCache<T, Y> { private final Map<T, Entry<Y>> cache = new LinkedHashMap<>(100, 0.75f, true); private final long initialMaxSize; private long maxSize; private long currentSize; ... public synchronized Y remove(@NonNull T key) { Entry<Y> entry = cache.remove(key); if (entry == null) { return null; } currentSize -= entry.size; return entry.value; } ... } public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>{ public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) { super(initialCapacity, loadFactor); this.accessOrder = accessOrder; } ... }复制代码
waitForExistingOrStartNewJob
那么回到Engine.load,loadFromMemory取不到, 则调用waitForExistingOrStartNewJob,代码如下
final class Jobs { private final Map<Key, EngineJob<?>> jobs = new HashMap<>(); private final Map<Key, EngineJob<?>> onlyCacheJobs = new HashMap<>(); ... } private <R> LoadStatus waitForExistingOrStartNewJob(...) { //先从jobs中取EngineJob EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache); if (current != null) { current.addCallback(cb, callbackExecutor); //取到则直接创建一个LoadStatus返回 return new LoadStatus(cb, current); } //取不到则通过engineJobFactory.build创建一个EngineJob EngineJob<R> engineJob = engineJobFactory.build( key, isMemoryCacheable, useUnlimitedSourceExecutorPool, useAnimationPool, onlyRetrieveFromCache); DecodeJob<R> decodeJob = decodeJobFactory.build( glideContext, model, key, signature, width, height, resourceClass, transcodeClass, priority, diskCacheStrategy, transformations, isTransformationRequired, isScaleOnlyOrNoTransform, onlyRetrieveFromCache, options, engineJob); //将创建的engineJob加入到jobs jobs.put(key, engineJob); engineJob.addCallback(cb, callbackExecutor); //调用start开启线程获取图片 engineJob.start(decodeJob); return new LoadStatus(cb, engineJob); }复制代码
engineJob.start
上面最重要的就是engineJob.start这一行,开启线程获取图片,start方法代码如下
public synchronized void start(DecodeJob<R> decodeJob) { this.decodeJob = decodeJob; GlideExecutor executor = //判断是否需要磁盘缓存,是则使用磁盘线程池,否则使用内存缓存线程池 decodeJob.willDecodeFromCache() ? diskCacheExecutor : getActiveSourceExecutor(); //执行job executor.execute(decodeJob); }复制代码
从GlideBuilder.build中可以找到diskCacheExecutor的初始化
diskCacheExecutor = GlideExecutor.newDiskCacheExecutor(); public final class GlideExecutor implements ExecutorService { public static GlideExecutor newDiskCacheExecutor() { return newDiskCacheBuilder().build(); } public static GlideExecutor.Builder newDiskCacheBuilder() { return new GlideExecutor.Builder(/*preventNetworkOperations=*/ true) .setThreadCount(DEFAULT_DISK_CACHE_EXECUTOR_THREADS) .setName(DEFAULT_DISK_CACHE_EXECUTOR_NAME); } GlideExecutor(ExecutorService delegate) { this.delegate = delegate; } public void execute(@NonNull Runnable command) { delegate.execute(command); } public static final class Builder { ... public GlideExecutor build() { if (TextUtils.isEmpty(name)) { throw new IllegalArgumentException( "Name must be non-null and non-empty, but given: " + name); } ThreadPoolExecutor executor = new ThreadPoolExecutor( corePoolSize, maximumPoolSize, /*keepAliveTime=*/ threadTimeoutMillis, TimeUnit.MILLISECONDS, new PriorityBlockingQueue<Runnable>(), new DefaultThreadFactory(name, uncaughtThrowableStrategy, preventNetworkOperations)); if (threadTimeoutMillis != NO_THREAD_TIMEOUT) { executor.allowCoreThreadTimeOut(true); } return new GlideExecutor(executor); } } }复制代码
不管是磁盘缓存还是内存最终都会调用DecodeJob(继承Runnable)的run,接着会调用runWrapped
class DecodeJob<R> implements DataFetcherGenerator.FetcherReadyCallback, Runnable, Comparable<DecodeJob<?>>, Poolable { public void run() { ... try { if (isCancelled) { notifyFailed(); return; } runWrapped(); } catch ( ... } private void runWrapped() { switch (runReason) { case INITIALIZE: //调用getNextStage后返回Stage.RESOURCE_CACHE stage = getNextStage(Stage.INITIALIZE); currentGenerator = getNextGenerator(); runGenerators(); break; case SWITCH_TO_SOURCE_SERVICE: runGenerators(); break; case DECODE_DATA: decodeFromRetrievedData(); break; default: throw new IllegalStateException("Unrecognized run reason: " + runReason); } } } //getNextState中会根据磁盘缓存的策略判断来指定Stage值 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: // Skip loading from source if the user opted to only retrieve the resource from cache. return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE; case SOURCE: case FINISHED: return Stage.FINISHED; default: throw new IllegalArgumentException("Unrecognized stage: " + current); } }复制代码
runReason在初始化DecodeJob的时候设置初始为INITIALIZE,所以会调用getNextGenerator,且getNextStage后stage为RESOURCE_CACHE,所以最终返回ResourceCacheGenerator
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); } }复制代码
runGenerators
DecodeJob.runWrapped最后会调用runGenerators
private void runGenerators() { ... while (!isCancelled && currentGenerator != null && !(isStarted = currentGenerator.startNext())) { stage = getNextStage(stage); currentGenerator = getNextGenerator(); if (stage == Stage.SOURCE) { reschedule(); return; } } ... }复制代码
其中while中的currentGenerator就是上面几个状态对应的ResourceCacheGenerator,DataCacheGenerator,SourceGenerator; 前两个都是缓存的让我们来看一下SourceGenerator的startNext;
SourceGenerator.startNext
runGenerators中最关键的一步是调用了currentGenerator.startNext
public boolean startNext() { ... while (!started && hasNextModelLoader()) { loadData = helper.getLoadData().get(loadDataListIndex++); if (loadData != null && (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource()) || helper.hasLoadPath(loadData.fetcher.getDataClass()))) { started = true; startNextLoad(loadData); } } return started; } private void startNextLoad(final LoadData<?> toStart) { //这里只需要关注loadData.fetcher.loadData方法 loadData.fetcher.loadData( helper.getPriority(), new DataCallback<Object>() { @Override public void onDataReady(@Nullable Object data) { if (isCurrentRequest(toStart)) { onDataReadyInternal(toStart, data); } } @Override public void onLoadFailed(@NonNull Exception e) { if (isCurrentRequest(toStart)) { onLoadFailedInternal(toStart, e); } } }); }复制代码
上面代码中helper.getLoadData代码如下
List<LoadData<?>> getLoadData() { if (!isLoadDataSet) { isLoadDataSet = true; loadData.clear(); List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model); //noinspection ForLoopReplaceableByForEach to improve perf for (int i = 0, size = modelLoaders.size(); i < size; i++) { ModelLoader<Object, ?> modelLoader = modelLoaders.get(i); LoadData<?> current = modelLoader.buildLoadData(model, width, height, options); if (current != null) { loadData.add(current); } } } return loadData; }复制代码
其中buildLoadData是在HttpGlideUrlLoader中实现的
HttpGlideUrlLoader.buildLoadData
public LoadData<InputStream> buildLoadData( @NonNull GlideUrl model, int width, int height, @NonNull Options options) { // GlideUrls memoize parsed URLs so caching them saves a few object instantiations and time // spent parsing urls. GlideUrl url = model; if (modelCache != null) { url = modelCache.get(model, 0, 0); if (url == null) { modelCache.put(model, 0, 0, model); url = model; } } int timeout = options.get(TIMEOUT); return new LoadData<>(url, new HttpUrlFetcher(url, timeout)); }复制代码
而SourceGenerator.startNext的startNextLoad中,调用了loadData.fetcher.loadData方法,而从上面代码最后一行我们知道fetcher的实际类型就是HttpUrlFetcher,那么我们看看其loadData方法的实现
HttpUrlFetcher.loadData
public void loadData( @NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) { long startTime = LogTime.getLogTime(); try { InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders()); callback.onDataReady(result); } catch (IOException e) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Failed to load data for url", e); } callback.onLoadFailed(e); } finally { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "Finished http url fetcher fetch in " + LogTime.getElapsedMillis(startTime)); } } }复制代码
可以看到其中调用了loadDataWithRedirects,代码如下:
private InputStream loadDataWithRedirects( URL url, int redirects, URL lastUrl, Map<String, String> headers) throws HttpException { ... urlConnection = buildAndConfigureConnection(url, headers); try { // Connect explicitly to avoid errors in decoders if connection fails. urlConnection.connect(); // Set the stream so that it's closed in cleanup to avoid resource leaks. See #2352. stream = urlConnection.getInputStream(); } catch (IOException e) { throw new HttpException( "Failed to connect or obtain data", getHttpStatusCodeOrInvalid(urlConnection), e); } if (isCancelled) { return null; } final int statusCode = getHttpStatusCodeOrInvalid(urlConnection); ... }复制代码
上面代码中我们看到了熟悉的urlConnection,那么看一下buildAndConfigureConnection方法的实现吧
private HttpURLConnection buildAndConfigureConnection(URL url, Map<String, String> headers) throws HttpException { HttpURLConnection urlConnection; try { urlConnection = connectionFactory.build(url); } catch (IOException e) { throw new HttpException("URL.openConnection threw", /*statusCode=*/ 0, e); } for (Map.Entry<String, String> headerEntry : headers.entrySet()) { urlConnection.addRequestProperty(headerEntry.getKey(), headerEntry.getValue()); } urlConnection.setConnectTimeout(timeout); urlConnection.setReadTimeout(timeout); urlConnection.setUseCaches(false); urlConnection.setDoInput(true); // Stop the urlConnection instance of HttpUrlConnection from following redirects so that // redirects will be handled by recursive calls to this method, loadDataWithRedirects. urlConnection.setInstanceFollowRedirects(false); return urlConnection; }复制代码
到此我们终于看到了网络请求相关的代码,原来Glide使用的HttpURLConnection进行网络请求
SourceGenerator.onDataReadyInternal
而从上面SourceGenerator.startNextNext中的loadData.fetcher.loadData的入参DataCallback的onDataReady我们知道,如果请求成功,会将资源通过onDataReady传递回去,其中调用了onDataReadyInternal,代码如下
void onDataReadyInternal(LoadData<?> loadData, Object data) { //获取磁盘加载策略 DiskCacheStrategy diskCacheStrategy = helper.getDiskCacheStrategy(); //判断是否缓存原始数据 if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) { dataToCache = data; // We might be being called back on someone else's thread. Before doing anything, we should // reschedule to get back onto Glide's thread. cb.reschedule(); } else { //cb为DecodeJob cb.onDataFetcherReady( loadData.sourceKey, data, loadData.fetcher, loadData.fetcher.getDataSource(), originalKey); } }复制代码
上面的cb实际为DecodeJob,那么来看一下DecodeJob.onDataFetcherReady
public void onDataFetcherReady( Key sourceKey, Object data, DataFetcher<?> fetcher, DataSource dataSource, Key attemptedKey) { this.currentSourceKey = sourceKey; this.currentData = data; this.currentFetcher = fetcher; this.currentDataSource = dataSource; this.currentAttemptingKey = attemptedKey; this.isLoadingFromAlternateCacheKey = sourceKey != decodeHelper.getCacheKeys().get(0); if (Thread.currentThread() != currentThread) { runReason = RunReason.DECODE_DATA; callback.reschedule(this); } else { GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData"); try { decodeFromRetrievedData(); } finally { GlideTrace.endSection(); } } }复制代码
上面代码中又调用了decodeFromRetrievedData,代码如下
private void decodeFromRetrievedData() { if (Log.isLoggable(TAG, Log.VERBOSE)) { logWithTimeAndKey( "Retrieved data", startFetchTime, "data: " + currentData + ", cache key: " + currentSourceKey + ", fetcher: " + currentFetcher); } Resource<R> resource = null; try { //解析图片 resource = decodeFromData(currentFetcher, currentData, currentDataSource); } catch (GlideException e) { e.setLoggingDetails(currentAttemptingKey, currentDataSource); throwables.add(e); } if (resource != null) { //通知图片获取完毕 notifyEncodeAndRelease(resource, currentDataSource, isLoadingFromAlternateCacheKey); } else { runGenerators(); } }复制代码
notifyEncodeAndRelease代码如下
private void notifyEncodeAndRelease( Resource<R> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) { if (resource instanceof Initializable) { ((Initializable) resource).initialize(); } Resource<R> result = resource; LockedResource<R> lockedResource = null; if (deferredEncodeManager.hasResourceToEncode()) { lockedResource = LockedResource.obtain(resource); result = lockedResource; } notifyComplete(result, dataSource, isLoadedFromAlternateCacheKey); stage = Stage.ENCODE; try { if (deferredEncodeManager.hasResourceToEncode()) { deferredEncodeManager.encode(diskCacheProvider, options); } } finally { if (lockedResource != null) { lockedResource.unlock(); } } // Call onEncodeComplete outside the finally block so that it's not called if the encode process // throws. onEncodeComplete(); }
作者:今阳
链接:https://juejin.cn/post/7019212031500746788