本篇将分析源码Glide.into()方法
Glide源码剖析-into
将分析源码Glide.into()
into() 可以发现,前面两个方法with()和load()都没有涉及到图片的请求、缓存、解码等别的逻辑。那么都会在into()里,所以这部分会非常复杂:muscle:加油
1 Glide.with(this ).load("图片资源" ).into(image)
重载方法 into()的重载方法和View的那套差不多,都是向下重复调用重载方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 #RequestBuilder @NonNull public <Y extends Target<TranscodeType>> Y into (@NonNull Y target) { return into(target, null , Executors.mainThreadExecutor()); } ---分割--- @NonNull @Synthetic <Y extends Target<TranscodeType>> Y into ( @NonNull Y target, @Nullable RequestListener<TranscodeType> targetListener, Executor callbackExecutor) { return into(target, targetListener, this , callbackExecutor); } ---分割--- 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 = 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; } requestManager.clear(target); target.setRequest(request); requestManager.track(target, request); return target; }
最终会还是会来到
1 2 3 4 into(@NonNull Y target, @Nullable RequestListener<TranscodeType> targetListener, BaseRequestOptions<?> options, Executor callbackExecutor){}
这个方法,我们一步一步分析
首先,会判断前面是否调用过load(),因为只有调用了load(),isMolderSet才会为true
1 2 3 4 5 #RequestBuilder if (!isModelSet) { throw new IllegalArgumentException("You must call #load() before calling #into()" ); } ...
保证调用顺序不发生错误
通过buildeRequest()构建了一个Request
1 2 3 4 #RequestBuilder ... Request request = buildRequest(target, targetListener, options, callbackExecutor); ...
那就先继续去看看buildRequest()
buildRequest() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #RequestBuilder private Request buildRequest ( Target<TranscodeType> target, @Nullable RequestListener<TranscodeType> targetListener, BaseRequestOptions<?> requestOptions, Executor callbackExecutor) { return buildRequestRecursive( new Object(), target, targetListener, null , transitionOptions, requestOptions.getPriority(), requestOptions.getOverrideWidth(), requestOptions.getOverrideHeight(), requestOptions, callbackExecutor); }
BaseRequestOptions:是之前load()创建RequestBuilder时,调用的apply设置的一些默认参数
transitionOptions:用于设置加载完成时在资源上使用的转换的基类
可以看到它又将参数和一些额外参数都传递进了buildRequestRecursive。到目前为止都还没有看到实际性的构建代码:sweat:,那就只能继续深入
buildRequestRecursive() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 #RequestBuilder private Request buildRequestRecursive ( Object requestLock, Target<TranscodeType> target, @Nullable RequestListener<TranscodeType> targetListener, @Nullable RequestCoordinator parentCoordinator, TransitionOptions<?, ? super TranscodeType> transitionOptions, Priority priority, int overrideWidth, int overrideHeight, BaseRequestOptions<?> requestOptions, Executor callbackExecutor) { ErrorRequestCoordinator errorRequestCoordinator = null ; if (errorBuilder != null ) { errorRequestCoordinator = new ErrorRequestCoordinator(requestLock, parentCoordinator); parentCoordinator = errorRequestCoordinator; } Request mainRequest = buildThumbnailRequestRecursive( requestLock, target, targetListener, parentCoordinator, transitionOptions, priority, overrideWidth, overrideHeight, requestOptions, callbackExecutor); if (errorRequestCoordinator == null ) { return mainRequest; } int errorOverrideWidth = errorBuilder.getOverrideWidth(); int errorOverrideHeight = errorBuilder.getOverrideHeight(); if (Util.isValidDimensions(overrideWidth, overrideHeight) && !errorBuilder.isValidOverride()) { errorOverrideWidth = requestOptions.getOverrideWidth(); errorOverrideHeight = requestOptions.getOverrideHeight(); } Request errorRequest = errorBuilder.buildRequestRecursive( requestLock, target, targetListener, errorRequestCoordinator, errorBuilder.transitionOptions, errorBuilder.getPriority(), errorOverrideWidth, errorOverrideHeight, errorBuilder, callbackExecutor); errorRequestCoordinator.setRequests(mainRequest, errorRequest); return errorRequestCoordinator; }
ErrorRequestCoordinator:为协调器,目的是可以让errorRequest和mainRequest一起工作
关于errorBuilder的这行代码,如果没有设置在主请求失败时开始新的请求(如下设置),那么是不会走最后去递归构建错误请求。
1 2 Glide.with(this ).load(url).error(Glide.with(this ).load(url)).into(imageView);
所以我们先看一下没有设置erro的情况
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #buildRequestRecursive Request mainRequest = buildThumbnailRequestRecursive( requestLock, target, targetListener, parentCoordinator, transitionOptions, priority, overrideWidth, overrideHeight, requestOptions, callbackExecutor); if (errorRequestCoordinator == null ) { return mainRequest; }
可以看到如果没有设置error,那么errorRequestCoordinator一定会为空,所以就到此为止返回一个buildThumbnailRequestRecursive出去。那么继续
buildThumbnailRequestRecursive() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 #RequestBuilder private Request buildThumbnailRequestRecursive ( Object requestLock, Target<TranscodeType> target, RequestListener<TranscodeType> targetListener, @Nullable RequestCoordinator parentCoordinator, TransitionOptions<?, ? super TranscodeType> transitionOptions, Priority priority, int overrideWidth, int overrideHeight, BaseRequestOptions<?> requestOptions, Executor callbackExecutor) { if (thumbnailBuilder != null ) { if (isThumbnailBuilt) { throw new IllegalStateException( "You cannot use a request as both the main request and a " + "thumbnail, consider using clone() on the request(s) passed to thumbnail()" ); } TransitionOptions<?, ? super TranscodeType> thumbTransitionOptions = thumbnailBuilder.transitionOptions; if (thumbnailBuilder.isDefaultTransitionOptionsSet) { thumbTransitionOptions = transitionOptions; } Priority thumbPriority = thumbnailBuilder.isPrioritySet() ? thumbnailBuilder.getPriority() : getThumbnailPriority(priority); int thumbOverrideWidth = thumbnailBuilder.getOverrideWidth(); int thumbOverrideHeight = thumbnailBuilder.getOverrideHeight(); if (Util.isValidDimensions(overrideWidth, overrideHeight) && !thumbnailBuilder.isValidOverride()) { thumbOverrideWidth = requestOptions.getOverrideWidth(); thumbOverrideHeight = requestOptions.getOverrideHeight(); } ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(requestLock, parentCoordinator); Request fullRequest = obtainRequest( requestLock, target, targetListener, requestOptions, coordinator, transitionOptions, priority, overrideWidth, overrideHeight, callbackExecutor); isThumbnailBuilt = true ; Request thumbRequest = thumbnailBuilder.buildRequestRecursive( requestLock, target, targetListener, coordinator, thumbTransitionOptions, thumbPriority, thumbOverrideWidth, thumbOverrideHeight, thumbnailBuilder, callbackExecutor); isThumbnailBuilt = false ; coordinator.setRequests(fullRequest, thumbRequest); return coordinator; } else if (thumbSizeMultiplier != null ) { ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(requestLock, parentCoordinator); Request fullRequest = obtainRequest( requestLock, target, targetListener, requestOptions, coordinator, transitionOptions, priority, overrideWidth, overrideHeight, callbackExecutor); BaseRequestOptions<?> thumbnailOptions = requestOptions.clone().sizeMultiplier(thumbSizeMultiplier); Request thumbnailRequest = obtainRequest( requestLock, target, targetListener, thumbnailOptions, coordinator, transitionOptions, getThumbnailPriority(priority), overrideWidth, overrideHeight, callbackExecutor); coordinator.setRequests(fullRequest, thumbnailRequest); return coordinator; } else { return obtainRequest( requestLock, target, targetListener, requestOptions, parentCoordinator, transitionOptions, priority, overrideWidth, overrideHeight, callbackExecutor); } }
“代码很长,你忍耐一下”条主要的分析把:collision:
这里有些地方和上面的error有点类似,比如说一开始就判断thumbnailBuilder 是否为空
thumbnailBuilder 也和error一样,只有设置了缩略图才会不为空
1 Glide.with(this ).load(url).thumbnail(Glide.with(this ).load(thumbnailUrl)).into(imageView);
thumbSizeMultiplier:不为空,说明设置了缩放比例(如下设置)
1 Glide.with(this ).load(url).thumbnail(0.5f ).into(imageView);
这里就先不去理分支了,先直接看获取原图。(套不下去了,太深了)可以看到,如果没有设置缩略图和缩略比例,那么就只会调用obtainRequest()
obtainRequest() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 #RequestBuilder private Request obtainRequest ( Object requestLock, Target<TranscodeType> target, RequestListener<TranscodeType> targetListener, BaseRequestOptions<?> requestOptions, RequestCoordinator requestCoordinator, TransitionOptions<?, ? super TranscodeType> transitionOptions, Priority priority, int overrideWidth, int overrideHeight, Executor callbackExecutor) { return SingleRequest.obtain( context, glideContext, requestLock, model, transcodeClass, requestOptions, overrideWidth, overrideHeight, priority, target, targetListener, requestListeners, requestCoordinator, glideContext.getEngine(), transitionOptions.getTransitionFactory(), callbackExecutor); }
SingleRequest 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 #SingleRequest public static <R> SingleRequest<R> obtain ( Context context, GlideContext glideContext, Object requestLock, Object model, Class<R> transcodeClass, BaseRequestOptions<?> requestOptions, int overrideWidth, int overrideHeight, Priority priority, Target<R> target, RequestListener<R> targetListener, @Nullable List<RequestListener<R>> requestListeners, RequestCoordinator requestCoordinator, Engine engine, TransitionFactory<? super R> animationFactory, Executor callbackExecutor) { return new SingleRequest<>( context, glideContext, requestLock, model, transcodeClass, requestOptions, overrideWidth, overrideHeight, priority, target, targetListener, requestListeners, requestCoordinator, engine, animationFactory, callbackExecutor); } ---分割--- private SingleRequest ( Context context, GlideContext glideContext, @NonNull Object requestLock, @Nullable Object model, Class<R> transcodeClass, BaseRequestOptions<?> requestOptions, int overrideWidth, int overrideHeight, Priority priority, Target<R> target, @Nullable RequestListener<R> targetListener, @Nullable List<RequestListener<R>> requestListeners, RequestCoordinator requestCoordinator, Engine engine, TransitionFactory<? super R> animationFactory, Executor callbackExecutor) { this .requestLock = requestLock; this .context = context; this .glideContext = glideContext; this .model = model; this .transcodeClass = transcodeClass; this .requestOptions = requestOptions; this .overrideWidth = overrideWidth; this .overrideHeight = overrideHeight; this .priority = priority; this .target = target; this .targetListener = targetListener; this .requestListeners = requestListeners; this .requestCoordinator = requestCoordinator; this .engine = engine; this .animationFactory = animationFactory; this .callbackExecutor = callbackExecutor; status = Status.PENDING; if (requestOrigin == null && glideContext.getExperiments().isEnabled(LogRequestOrigins.class)) { requestOrigin = new RuntimeException("Glide request origin trace" ); } }
泪目,终于到头了:cry:这里也是将参数传递进去,最终构建了一个SingleRequest出来。可是我们一开始不是要的是Request吗?
1 public final class SingleRequest <R > implements Request , SizeReadyCallback , ResourceCallback {}
SingleRequest是Request的具体实现
回到开头,现在Request有了,最上面的代码中还有一个地方没处理,那就是track()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #RequestBuilder private <Y extends Target<TranscodeType>> Y into ( @NonNull Y target, @Nullable RequestListener<TranscodeType> targetListener, BaseRequestOptions<?> options, Executor callbackExecutor) { ... Request request = buildRequest(target, targetListener, options, callbackExecutor); ... Request previous = target.getRequest(); requestManager.clear(target); target.setRequest(request); requestManager.track(target, request); return target; }
track() 1 2 3 4 5 6 7 8 9 10 11 12 13 #RequestManager @GuardedBy("this") private final TargetTracker targetTracker = new TargetTracker();@GuardedBy("this") private final RequestTracker requestTracker;synchronized void track (@NonNull Target<?> target, @NonNull Request request) { targetTracker.track(target); requestTracker.runRequest(request); }
很明显,就是将传入进来的Target加入到TargetTracker里去,再调用requestTracker.runRequest()来运行Request
TargetTracker 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 public final class TargetTracker implements LifecycleListener { private final Set<Target<?>> targets = Collections.newSetFromMap(new WeakHashMap<Target<?>, Boolean>()); public void track (@NonNull Target<?> target) { targets.add(target); } public void untrack (@NonNull Target<?> target) { targets.remove(target); } @Override public void onStart () { for (Target<?> target : Util.getSnapshot(targets)) { target.onStart(); } } @Override public void onStop () { for (Target<?> target : Util.getSnapshot(targets)) { target.onStop(); } } @Override public void onDestroy () { for (Target<?> target : Util.getSnapshot(targets)) { target.onDestroy(); } } @NonNull public List<Target<?>> getAll() { return Util.getSnapshot(targets); } public void clear () { targets.clear(); } }
TargetTracker看起来还是比较简单的,track()就是将Target加入一个Set集合中去,其余的操作都是对Set集合中的数据进行遍历操作
Collections.newSetFromMap():JDK1.6开始提供的,用于将生成的Map包装成Set,这样这个Set和被包装的Map拥有相同的key顺序。简单来说就是你可以使用这个工厂类来包装WeakHashMap来生成一个WeakHashSet,因为没有WeakHashSet这个现成的类可用
RequestTracker 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public class RequestTracker { private static final String TAG = "RequestTracker" ; private final Set<Request> requests = Collections.newSetFromMap(new WeakHashMap<Request, Boolean>()); private final Set<Request> pendingRequests = new HashSet<>(); private boolean isPaused; 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); } } }
RequestTracker.runRequest()
也还是蛮简单的,一开始也是将request
添加到Set集合里去,之后再判断当前是否处于停止状态,是则清空请求,否则开始请求
我们继续深入一下RequestTracker
,查看一下RequestTracker.begin()
,由于begin是一个接口,SingleRequest
又是Request
的具体实现,那我们相当于是去看一下SingleRequest.begin()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 #SingleRequest @Override public void begin () { synchronized (requestLock) { assertNotCallingCallbacks(); stateVerifier.throwIfRecycled(); startTime = LogTime.getLogTime(); if (model == null ) { if (Util.isValidDimensions(overrideWidth, overrideHeight)) { width = overrideWidth; height = overrideHeight; } int logLevel = getFallbackDrawable() == null ? Log.WARN : Log.DEBUG; onLoadFailed(new GlideException("Received null model" ), logLevel); return ; } if (status == Status.RUNNING) { throw new IllegalArgumentException("Cannot restart a running request" ); } if (status == Status.COMPLETE) { onResourceReady( resource, DataSource.MEMORY_CACHE, false ); return ; } cookie = GlideTrace.beginSectionAsync(TAG); status = Status.WAITING_FOR_SIZE; if (Util.isValidDimensions(overrideWidth, overrideHeight)) { 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)); } } }
先判断CallingCallbacks()是否为空
再判断加载资源是否为空,空的话则调用加载失败的回调
1 2 3 4 5 6 7 8 9 10 11 12 13 #SingleRequest if (model == null ) { if (Util.isValidDimensions(overrideWidth, overrideHeight)) { width = overrideWidth; height = overrideHeight; } int logLevel = getFallbackDrawable() == null ? Log.WARN : Log.DEBUG; onLoadFailed(new GlideException("Received null model" ), logLevel); return ; } ...
其次再判断当前的状态,是否在运行中,是否完成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ... #SingleRequest if (status == Status.RUNNING) { throw new IllegalArgumentException("Cannot restart a running request" ); } if (status == Status.COMPLETE) { onResourceReady( resource, DataSource.MEMORY_CACHE, false ); return ; } ...
接下来就是判断是否设置了overrideWidth、overrideHeight
1 2 3 4 5 6 7 #SingleRequest ... if (Util.isValidDimensions(overrideWidth, overrideHeight)) { onSizeReady(overrideWidth, overrideHeight); } else { target.getSize(this ); }
这里如果设置了overrideWidth、overrideHeight,则会直接调用onSizeRead(),否则的话,会调用getSize()
设置override
1 2 Glide.with(this ).load(url).override(100 ,100 ).into(imageView);
那就继续看一下getSize()方法
1 2 3 4 5 6 7 8 9 10 11 #Target public interface Target <R > extends LifecycleListener { ... void getSize (@NonNull SizeReadyCallback cb) ; ... } ---分割--- #SizeReadyCallback public interface SizeReadyCallback { void onSizeReady (int width, int height) ; }
getSize()内部是通过ViewTreeObserver来监听ImageView的高宽,最终也还是调用onSizeReady()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 #SingleRequest @Override public void onSizeReady (int width, int height) { stateVerifier.throwIfRecycled(); synchronized (requestLock) { if (IS_VERBOSE_LOGGABLE) { logV("Got onSizeReady in " + LogTime.getElapsedMillis(startTime)); } if (status != Status.WAITING_FOR_SIZE) { return ; } status = Status.RUNNING; float sizeMultiplier = requestOptions.getSizeMultiplier(); this .width = maybeApplySizeMultiplier(width, sizeMultiplier); this .height = maybeApplySizeMultiplier(height, sizeMultiplier); if (IS_VERBOSE_LOGGABLE) { logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime)); } 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 ; } if (IS_VERBOSE_LOGGABLE) { logV("finished onSizeReady in " + LogTime.getElapsedMillis(startTime)); } } }
首先将状态设置为运行中
再根据缩略比例来获取图片高宽
1 2 3 4 5 6 7 #onSizeReady ... float sizeMultiplier = requestOptions.getSizeMultiplier();this .width = maybeApplySizeMultiplier(width, sizeMultiplier);this .height = maybeApplySizeMultiplier(height, sizeMultiplier);...
最后调用engine.load()进行加载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #onSizeReady ... 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); ...
这里着重关注engine.load()
方法,可以猜测为正在加载的部分
Engine.load() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 #Engine 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 ) { return waitForExistingOrStartNewJob( glideContext, model, signature, width, height, resourceClass, transcodeClass, priority, diskCacheStrategy, transformations, isTransformationRequired, isScaleOnlyOrNoTransform, options, isMemoryCacheable, useUnlimitedSourceExecutorPool, useAnimationPool, onlyRetrieveFromCache, cb, callbackExecutor, key, startTime); } } cb.onResourceReady( memoryResource, DataSource.MEMORY_CACHE, false ); return null ; }
上述代码做了4件事情
使用参数构建了个EngineKey
1 2 3 4 5 6 7 8 9 10 11 EngineKey key = keyFactory.buildKey( model, signature, width, height, transformations, resourceClass, transcodeClass, options);
使用EngineKey去获取缓存中的资源,先从内存中进行获取
1 2 memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);
如果获取不到,则等待或新开启一个EngineJob
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 if (memoryResource == null ) { return waitForExistingOrStartNewJob( glideContext, model, signature, width, height, resourceClass, transcodeClass, priority, diskCacheStrategy, transformations, isTransformationRequired, isScaleOnlyOrNoTransform, options, isMemoryCacheable, useUnlimitedSourceExecutorPool, useAnimationPool, onlyRetrieveFromCache, cb, callbackExecutor, key, startTime); }
如果获取成功,则调用加载成功的回调
1 2 3 4 cb.onResourceReady( memoryResource, DataSource.MEMORY_CACHE, false ); return null ;
接下来先不讲解缓存,先继续将主要流程,缓存将再下面部分再进行讲解
waitForExistingOrStartNewJob 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 #Engine private final Jobs jobs;private <R> LoadStatus waitForExistingOrStartNewJob ( 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, EngineKey key, long startTime) { EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache); if (current != null ) { current.addCallback(cb, callbackExecutor); if (VERBOSE_IS_LOGGABLE) { logWithTimeAndKey("Added to existing load" , startTime, key); } return new LoadStatus(cb, current); } 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); jobs.put(key, engineJob); engineJob.addCallback(cb, callbackExecutor); engineJob.start(decodeJob); if (VERBOSE_IS_LOGGABLE) { logWithTimeAndKey("Started new load" , startTime, key); } return new LoadStatus(cb, engineJob); }
waitForExistingOrStartNewJob()做了6件事情
从成员变量jobs中获取EngineJob,如果获取不为空,则表示当前有正在执行的EngineJob,给EngineJob添加回调并返回新创建的LoadStatus()加载状态
1 2 3 4 5 6 7 8 9 EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache); if (current != null ) { current.addCallback(cb, callbackExecutor); if (VERBOSE_IS_LOGGABLE) { logWithTimeAndKey("Added to existing load" , startTime, key); } return new LoadStatus(cb, current); }
获取为空的话,则通过EngineJob工厂类来创建EngineJob。该类主要用来管理加载以及当加载完成时通知回调
1 2 3 4 5 6 7 8 EngineJob<R> engineJob = engineJobFactory.build( key, isMemoryCacheable, useUnlimitedSourceExecutorPool, useAnimationPool, onlyRetrieveFromCache);
使用DecodeJob工厂类来创建DecodeJob。该类主要负责图片的解码,实现了 Runnable 接口,属于一个任务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 DecodeJob<R> decodeJob = decodeJobFactory.build( glideContext, model, key, signature, width, height, resourceClass, transcodeClass, priority, diskCacheStrategy, transformations, isTransformationRequired, isScaleOnlyOrNoTransform, onlyRetrieveFromCache, options, engineJob);
将新创建的EngineJob添加到成员变量jobs中去
1 2 jobs.put(key, engineJob);
给新创建的EngineJob添加上回调并调用start()
1 2 3 engineJob.addCallback(cb, callbackExecutor); engineJob.start(decodeJob);
返回加载状态
1 2 3 4 5 if (VERBOSE_IS_LOGGABLE) { logWithTimeAndKey("Started new load" , startTime, key); } return new LoadStatus(cb, engineJob);
所以接下来我们需要先关注一下engineJob.start()
1 2 3 4 5 public synchronized void start (DecodeJob<R> decodeJob) { this .decodeJob = decodeJob; GlideExecutor executor = decodeJob.willDecodeFromCache() ? diskCacheExecutor : getActiveSourceExecutor(); executor.execute(decodeJob); }
上述代码就是将传入进来的DecodeJob放入线程池中去运行
DecodeJob 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 #DecodeJob public void run () { GlideTrace.beginSectionFormat("DecodeJob#run(reason=%s, model=%s)" , runReason, model); DataFetcher<?> localFetcher = currentFetcher; try { if (isCancelled) { notifyFailed(); return ; } runWrapped(); } catch (CallbackException e) { throw e; } catch (Throwable t) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d( TAG, "DecodeJob threw unexpectedly" + ", isCancelled: " + isCancelled + ", stage: " + stage,t); } if (stage != Stage.ENCODE) { throwables.add(t); notifyFailed(); } if (!isCancelled) { throw t; } throw t; } finally { if (localFetcher != null ) { localFetcher.cleanup(); } GlideTrace.endSection(); } }
判断是否被取消,如果取消了则调用加载失败
1 2 3 4 5 6 7 ... if (isCancelled) { notifyFailed(); return ; } ...
执行
真正的执行都在runWrapped中
判断状态码是否解码
1 2 3 4 5 6 7 ... if (stage != Stage.ENCODE) { throwables.add(t); notifyFailed(); } ...
runWrapped() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #DecodeJob private void runWrapped () { switch (runReason) { case INITIALIZE: 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); } }
runReason是有默认值的,默认为INITIALIZE
1 2 3 4 #DecodeJob DecodeJob<R> init (...) { this .runReason = RunReason.INITIALIZE; }
接下来将会通过INITIALIZE来获取资源状态
1 2 3 4 ... stage = getNextStage(Stage.INITIALIZE); ...
getNextStage() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #DecodeJob 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; case SOURCE: case FINISHED: return Stage.FINISHED; default : throw new IllegalArgumentException("Unrecognized stage: " + current); } }
首先会因为传递进来的是INITIALIZE,所以会进入第一个分支。内部则会判断是否使用内存缓存,如果使用的话,返回状态Stage.RESOURCE_CACHE。不使用的话,则继续递归传入下一个分支
回到runWrapped(),之后会通过资源状态来获取资源执行器
1 2 3 4 ... currentGenerator = getNextGenerator(); ...
getNextGenerator() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #DecodeJob 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); } }
如果禁用了内存缓存和硬盘缓存,那么这里的stage
会是Stage.SOURCE
,则会返回SourceGenerator()
,拿到资源执行器之后,就是开始执行了,调用了runGenerators()
方法
runGenerators() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #DecodeJob private void runGenerators () { currentThread = Thread.currentThread(); startFetchTime = LogTime.getLogTime(); boolean isStarted = false ; while (!isCancelled && currentGenerator != null && !(isStarted = currentGenerator.startNext())) { stage = getNextStage(stage); currentGenerator = getNextGenerator(); if (stage == Stage.SOURCE) { reschedule(); return ; } } if ((stage == Stage.FINISHED || isCancelled) && !isStarted) { notifyFailed(); } }
while条件中调用了currentGenerator.startNext()
,由这里的currentGenerator
是SourceGenerator
,所以实际上是在调用SourceGenerator.starNext()
SourceGenerator 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 public boolean startNext () { if (dataToCache != null ) { Object data = dataToCache; dataToCache = null ; try { boolean isDataInCache = cacheData(data); if (!isDataInCache) { return true ; } } catch (IOException e) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Failed to properly rewind or write data to cache" , e); } } } if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) { return true ; } sourceCacheGenerator = null ; loadData = null ; boolean started = false ; 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; }
这里先是使用了helper.getLoadData.get()
来获取loadData
,再进行判空,如果不为空的话,则调用startNextLoad()
helper.getLoadData.get() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #DecodeHelper List<LoadData<?>> getLoadData() { if (!isLoadDataSet) { isLoadDataSet = true ; loadData.clear(); List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model); 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; }
先通过成员变量modelLoaders
,获取一个ModelLoader
出来
再调用buildLoadData
来构建一个LoadData
buildLoadData
是一个接口,由于我们当前的是SourceGenerator
,也就是只是网络加载,所以这里的buildLoadData
实际上是HttpGlideUrlLoader.buildLoadData()
HttpGlideUrlLoader.buildLoadData() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #HttpGlideUrlLoader public LoadData<InputStream> buildLoadData ( @NonNull GlideUrl model, int width, int height, @NonNull Options options) { 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)); }
startNextLoad 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #SourceGenerator private void startNextLoad (final LoadData<?> toStart) { 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); } } }); }
loadData.fetcher其实就是刚刚返回LoadData的时候顺便实例化的HttpUrlFetcher
1 2 3 4 # interface ModelLoader public LoadData (@NonNull Key sourceKey, @NonNull DataFetcher<Data> fetcher) { this (sourceKey, Collections.<Key>emptyList(), fetcher); }
所以这里是调用HttpUrlFetcher.loadData()
HttpUrlFetcher.loadData() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Override 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)); } } }
HttpUrlFetcher.loadData()中,要关注两个方法,一个是loadDataWithRedirects(),另一个则是callback.onDataReady()
我们继续顺着下去,去看一下onDataReadyInternal()
onDataReadyInternal 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #SourceGenerator private final FetcherReadyCallback cb;@Synthetic void onDataReadyInternal (LoadData<?> loadData, 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); } }
一开始还是一如既往的进行判空和一些别的判断,之后就是调用了FetcherReadyCallback.onDataFetcherReady
FetcherReadyCallback是个接口,只有SourceGenerator和DecodeJob实现了。所以这里实际上是调用DecodeJob.onDataFetcherReady()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #DecodeJob 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(),经过了这么多的跳转,终于要开始解码了
decodeFromRetrievedData() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 #DecodeJob private DataFetcher<?> currentFetcher;private Object currentData;private DataSource currentDataSource; 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(); } }
别的我们都先不管了,先把主流程走一遍,这里有两个地方需要注意,decodeFromData(解码)、notifyEncodeAndRelease(解码完毕,进行通知)
decodeFromData 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #DecodeJob private <Data> Resource<R> decodeFromData ( DataFetcher<?> fetcher, Data data, DataSource dataSource) throws GlideException { try { if (data == null ) { return null ; } long startTime = LogTime.getLogTime(); Resource<R> result = decodeFromFetcher(data, dataSource); if (Log.isLoggable(TAG, Log.VERBOSE)) { logWithTimeAndKey("Decoded result " + result, startTime); } return result; } finally { fetcher.cleanup(); } }
decodeFromFetcher 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #DecodeJob private <Data> Resource<R> decodeFromFetcher (Data data, DataSource dataSource) throws GlideException { LoadPath<Data, ?, R> path = decodeHelper.getLoadPath((Class<Data>) data.getClass()); return runLoadPath(data, dataSource, path); } ---分割--- private <Data, ResourceType> Resource<R> runLoadPath ( Data data, DataSource dataSource, LoadPath<Data, ResourceType, R> path) throws GlideException { Options options = getOptionsWithHardwareConfig(dataSource); DataRewinder<Data> rewinder = glideContext.getRegistry().getRewinder(data); try { return path.load( rewinder, options, width, height, new DecodeCallback<ResourceType>(dataSource)); } finally { rewinder.cleanup(); } }
最终还是将任务传递给了path.load()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #LoadPath public Resource<Transcode> load ( DataRewinder<Data> rewinder, @NonNull Options options, int width, int height, DecodePath.DecodeCallback<ResourceType> decodeCallback) throws GlideException { List<Throwable> throwables = Preconditions.checkNotNull(listPool.acquire()); try { return loadWithExceptionList(rewinder, options, width, height, decodeCallback, throwables); } finally { listPool.release(throwables); } } ---分割--- private Resource<Transcode> loadWithExceptionList ( DataRewinder<Data> rewinder, @NonNull Options options, int width, int height, DecodePath.DecodeCallback<ResourceType> decodeCallback, List<Throwable> exceptions) throws GlideException { Resource<Transcode> result = null ; for (int i = 0 , size = decodePaths.size(); i < size; i++) { DecodePath<Data, ResourceType, Transcode> path = decodePaths.get(i); try { result = path.decode(rewinder, width, height, options, decodeCallback); } catch (GlideException e) { exceptions.add(e); } if (result != null ) { break ; } } if (result == null ) { throw new GlideException(failureMessage, new ArrayList<>(exceptions)); } return result; }
这里是将解码的任务交给了Decode Path来完成,所以DecodePath.decode()
才是真正开始解析数据的
DecodePath 1 2 3 4 5 6 7 8 9 10 11 12 #DecodePath public Resource<Transcode> decode ( DataRewinder<DataType> rewinder, int width, int height, @NonNull Options options, DecodeCallback<ResourceType> callback) throws GlideException { Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options); Resource<ResourceType> transformed = callback.onResourceDecoded(decoded); return transcoder.transcode(transformed, options); }
将图片资源进行解码成原始图片
1 Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);
decodeResource 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 #DecodePath @NonNull private Resource<ResourceType> decodeResource ( DataRewinder<DataType> rewinder, int width, int height, @NonNull Options options) throws GlideException { List<Throwable> exceptions = Preconditions.checkNotNull(listPool.acquire()); try { return decodeResourceWithList(rewinder, width, height, options, exceptions); } finally { listPool.release(exceptions); } } ------------ @NonNull private Resource<ResourceType> decodeResourceWithList ( DataRewinder<DataType> rewinder, int width, int height, @NonNull Options options, List<Throwable> exceptions) throws GlideException { Resource<ResourceType> result = null ; for (int i = 0 , size = decoders.size(); i < size; i++) { ResourceDecoder<DataType, ResourceType> decoder = decoders.get(i); try { DataType data = rewinder.rewindAndGet(); if (decoder.handles(data, options)) { data = rewinder.rewindAndGet(); result = decoder.decode(data, width, height, options); } } catch (IOException | RuntimeException | OutOfMemoryError e) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "Failed to decode data for " + decoder, e); } exceptions.add(e); } if (result != null ) { break ; } } if (result == null ) { throw new GlideException(failureMessage, new ArrayList<>(exceptions)); } return result; }
可以看到,这里遍历拿到可以解码当前数据的资源解码器,然后调用 decode() 方法进行解码。
因为当前数据是 Input Stream,所以这里遍历拿到的 Resource Decoder 其实是 StreamBitmapDecoder,所以调用的是 StreamBitmapDecoder.decode()
StreamBitmapDecoder的内部是调用Downsampler.decode()
将输入流解码变成Bitmap,最后将Bitmap包装成Resource返回
将原始图片通过回调通知Decode Job
回调最终会回到DecodeJob.onResourceDecoded()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 <Z> Resource<Z> onResourceDecoded (DataSource dataSource, @NonNull Resource<Z> decoded) { @SuppressWarnings("unchecked") Class<Z> resourceSubClass = (Class<Z>) decoded.get().getClass(); Transformation<Z> appliedTransformation = null ; Resource<Z> transformed = decoded; if (dataSource != DataSource.RESOURCE_DISK_CACHE) { appliedTransformation = decodeHelper.getTransformation(resourceSubClass); transformed = appliedTransformation.transform(glideContext, decoded, width, height); } if (!decoded.equals(transformed)) { decoded.recycle(); } final EncodeStrategy encodeStrategy; final ResourceEncoder<Z> encoder; if (decodeHelper.isResourceEncoderAvailable(transformed)) { encoder = decodeHelper.getResultEncoder(transformed); encodeStrategy = encoder.getEncodeStrategy(options); } else { encoder = null ; encodeStrategy = EncodeStrategy.NONE; } Resource<Z> result = transformed; boolean isFromAlternateCacheKey = !decodeHelper.isSourceKey(currentSourceKey); if (diskCacheStrategy.isResourceCacheable( isFromAlternateCacheKey, dataSource, encodeStrategy)) { if (encoder == null ) { throw new Registry.NoResultEncoderAvailableException(transformed.get().getClass()); } final Key key; switch (encodeStrategy) { case SOURCE: key = new DataCacheKey(currentSourceKey, signature); break ; case TRANSFORMED: key = new ResourceCacheKey( decodeHelper.getArrayPool(), currentSourceKey, signature, width, height, appliedTransformation, resourceSubClass, options); break ; default : throw new IllegalArgumentException("Unknown strategy: " + encodeStrategy); } LockedResource<Z> lockedResult = LockedResource.obtain(transformed); deferredEncodeManager.init(key, encoder, lockedResult); result = lockedResult; } return result; }
这里是进行资源转换的,也就是如果我们设置了center Crop之类的,那么就会进行对应的转换,最后将结果返回出去
调用 BitmapDrawableTranscoder.transcode()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public Resource<BitmapDrawable> transcode ( @NonNull Resource<Bitmap> toTranscode, @NonNull Options options) { return LazyBitmapDrawableResource.obtain(resources, toTranscode); } --------- @Nullable public static Resource<BitmapDrawable> obtain ( @NonNull Resources resources, @Nullable Resource<Bitmap> bitmapResource) { if (bitmapResource == null ) { return null ; } return new LazyBitmapDrawableResource(resources, bitmapResource); } --------- private LazyBitmapDrawableResource ( @NonNull Resources resources, @NonNull Resource<Bitmap> bitmapResource) { this .resources = Preconditions.checkNotNull(resources); this .bitmapResource = Preconditions.checkNotNull(bitmapResource); }
这里就是将传入进来的Bitmap封装再Resource里面,顺便再进行一下判空处理
notifyEncodeAndRelease 解码部分完成了,剩下就是要将结果通知出去
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 private void notifyEncodeAndRelease ( Resource<R> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) { GlideTrace.beginSection("DecodeJob.notifyEncodeAndRelease" ); try { 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(); } } onEncodeComplete(); } finally { GlideTrace.endSection(); } }
这里通过notifyComplete()
进一步的将结果通知给外部,notifyComlete内部使用通过callback.onResourceReady()
来进行回调
1 2 3 4 5 6 7 #DecodeJob private void notifyComplete ( Resource<R> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) { setNotifiedOrThrow(); callback.onResourceReady(resource, dataSource, isLoadedFromAlternateCacheKey); }
而实现了callback的只有Engine Job一个,所以这里是将结果返回给了Engine Job
EnginJob 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 @Override public void onResourceReady ( Resource<R> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) { synchronized (this ) { this .resource = resource; this .dataSource = dataSource; this .isLoadedFromAlternateCacheKey = isLoadedFromAlternateCacheKey; } notifyCallbacksOfResult(); } @Synthetic void notifyCallbacksOfResult () { ResourceCallbacksAndExecutors copy; Key localKey; EngineResource<?> localResource; synchronized (this ) { stateVerifier.throwIfRecycled(); if (isCancelled) { resource.recycle(); release(); return ; } else if (cbs.isEmpty()) { throw new IllegalStateException("Received a resource without any callbacks to notify" ); } else if (hasResource) { throw new IllegalStateException("Already have resource" ); } engineResource = engineResourceFactory.build(resource, isCacheable, key, resourceListener); hasResource = true ; copy = cbs.copy(); incrementPendingCallbacks(copy.size() + 1 ); localKey = key; localResource = engineResource; } engineJobListener.onEngineJobComplete(this , localKey, localResource); for (final ResourceCallbackAndExecutor entry : copy) { entry.executor.execute(new CallResourceReady(entry.cb)); } decrementPendingCallbacks(); }
这里有两个重要部分,第一个是engineJobListener.onEngineJobComplete()
、第二个为entry.executor.execute()
engineJobListener.onEngineJobComplete()
内部主要判断是否配置了内存缓存,如果有,则进行内存缓存
entry.executor.execute()
这里的executor其实就是最上方的传入进来的Executors.mainThreadExecutor()
1 2 3 4 5 #RequestBuilder @NonNull public <Y extends Target<TranscodeType>> Y into (@NonNull Y target) { return into(target, null , Executors.mainThreadExecutor()); }
Executors
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 public final class Executors { private Executors () { } private static final Executor MAIN_THREAD_EXECUTOR = new Executor() { @Override public void execute (@NonNull Runnable command) { Util.postOnUiThread(command); } }; private static final Executor DIRECT_EXECUTOR = new Executor() { @Override public void execute (@NonNull Runnable command) { command.run(); } }; public static Executor mainThreadExecutor () { return MAIN_THREAD_EXECUTOR; } public static Executor directExecutor () { return DIRECT_EXECUTOR; } @VisibleForTesting public static void shutdownAndAwaitTermination (ExecutorService pool) { long shutdownSeconds = 5 ; pool.shutdownNow(); try { if (!pool.awaitTermination(shutdownSeconds, TimeUnit.SECONDS)) { pool.shutdownNow(); if (!pool.awaitTermination(shutdownSeconds, TimeUnit.SECONDS)) { throw new RuntimeException("Failed to shutdown" ); } } } catch (InterruptedException ie) { pool.shutdownNow(); Thread.currentThread().interrupt(); throw new RuntimeException(ie); } } }
Executors.mainThreadExecutor()
其实就是创建了个Executors实例,然后内部重写了execute()方法,还是使用Handler来post一个一个任务并切换到了主线程,所以现在只用去查看CallResourceReady.run()
即可
CallResourceReady 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #EngineJob private class CallResourceReady implements Runnable { private final ResourceCallback cb; CallResourceReady(ResourceCallback cb) { this .cb = cb; } @Override public void run () { synchronized (cb.getLock()) { synchronized (EngineJob.this ) { if (cbs.contains(cb)) { engineResource.acquire(); callCallbackOnResourceReady(cb); removeCallback(cb); } decrementPendingCallbacks(); } } } } void callCallbackOnResourceReady (ResourceCallback cb) { try { cb.onResourceReady(engineResource, dataSource); } catch (Throwable t) { throw new CallbackException(t); } }
这里的cb.onResourceReady()
是直接回调给了SingleRequest.onResourceReady()
,SingleRequest.onResourceReady()
内部主要是处理一些加载失败的判断,然后调用重载方法
1 2 3 4 onResourceReady( (Resource<R>) resource, (R) received, dataSource, isLoadedFromAlternateCacheKey); }
onResourceReady 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 private void onResourceReady ( Resource<R> resource, R result, DataSource dataSource, boolean isAlternateCacheKey) { boolean isFirstResource = isFirstReadyResource(); status = Status.COMPLETE; this .resource = resource; if (glideContext.getLogLevel() <= Log.DEBUG) { Log.d( GLIDE_TAG, "...“); } 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是ImageViewTarget,所以这里是直接回调给ImageViewTarget target.onResourceReady(result, animation); } } finally { isCallingCallbacks = false; } // 通知加载成功 notifyLoadSuccess(); }
最后再ImageViewTarget.onResourceReady()
内部会判断传入的animation是否为空,为空的话就会直接设置图片。不为空的话,则会调用animation
animation为空
1 2 3 4 5 6 7 8 9 10 11 12 13 #ImageViewTarget private void setResourceInternal (@Nullable Z resource) { setResource(resource); maybeUpdateAnimatable(resource); } --------- #BitmapImageViewTarget @Override protected void setResource (Bitmap resource) { view.setImageBitmap(resource); }
最终将图片设置到Image View上去
animation不为空
1 2 3 4 5 6 7 8 9 #ImageViewTarget private void maybeUpdateAnimatable (@Nullable Z resource) { if (resource instanceof Animatable) { animatable = (Animatable) resource; animatable.start(); } else { animatable = null ; } }
总结 into()方法十分复杂,主要就是先从内存中进行获取,没有的话,再去硬盘中获取,都没有则通过HttpURLconnection来进行网络请求,其次在将结果给Decode Path进行解码,解码完成将结果封装成Resource通过回调层层传递,中间顺便判断是否需要缓存到硬盘、内存、是否需要进行形状变化。最终将结果设置到Image View上去