接著上一篇扣墩,with方法獲取到RequestManager 對象,它實現(xiàn)了LifecycleListener接口办绝,這意味著试伙,頁面生命周期的觸發(fā)會通知到RequestManager 類,但根據(jù)上一篇分析勤哗,在此之前薛闪,它必須先被添加到ActivityFragmentLifecycle的成員變量lifecycleListeners 集合中 ,我們先看它的構(gòu)造方法俺陋。
public class RequestManager implements LifecycleListener,
ModelTypes<RequestBuilder<Drawable>> {
private final ConnectivityMonitor connectivityMonitor;
private final Handler mainHandler = new Handler(Looper.getMainLooper());
private final CopyOnWriteArrayList<RequestListener<Object>> defaultRequestListeners;
private final Runnable addSelfToLifecycle = new Runnable() {
@Override
public void run() {
lifecycle.addListener(RequestManager.this);
}
};
public RequestManager(
@NonNull Glide glide, @NonNull Lifecycle lifecycle,
@NonNull RequestManagerTreeNode treeNode, @NonNull Context context) {
this(
glide,
lifecycle,
treeNode,
new RequestTracker(),
glide.getConnectivityMonitorFactory(),
context);
}
RequestManager(
Glide glide,
Lifecycle lifecycle,
RequestManagerTreeNode treeNode,
RequestTracker requestTracker,
ConnectivityMonitorFactory factory,
Context context) {
this.glide = glide;
this.lifecycle = lifecycle;
this.treeNode = treeNode;
this.requestTracker = requestTracker;
this.context = context;
//網(wǎng)絡(luò)監(jiān)聽器
connectivityMonitor =
factory.build(
context.getApplicationContext(),
new RequestManagerConnectivityListener(requestTracker));
//后臺線程豁延,切到主線程中添加
if (Util.isOnBackgroundThread()) {
mainHandler.post(addSelfToLifecycle);
} else {
//添加自己到ActivityFragmentLifecycle的集合中
lifecycle.addListener(this);
}
//添加網(wǎng)絡(luò)監(jiān)聽器
lifecycle.addListener(connectivityMonitor);
defaultRequestListeners =
new CopyOnWriteArrayList<>(glide.getGlideContext().getDefaultRequestListeners());
setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());
//保存到glide的成員列表中
glide.registerRequestManager(this);
}
}
可以看出昙篙,ConnectivityMonitor 也實現(xiàn)了LifecycleListener接口,因為它也被添加到lifecycleListeners 集合中诱咏,跟隨Framgent的生命周期回調(diào)苔可。
獲取到RequestManager對象后,將調(diào)用load方法袋狞。
public class RequestManager implements LifecycleListener,
ModelTypes<RequestBuilder<Drawable>> {
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);
}
//轉(zhuǎn)碼后的類型為Bitmap.class
public RequestBuilder<Bitmap> asBitmap() {
return as(Bitmap.class).apply(DECODE_TYPE_BITMAP);
}
//轉(zhuǎn)碼后的類型為Drawable.class
public RequestBuilder<Drawable> asDrawable() {
return as(Drawable.class);
}
//獲取RequestBuilder
public <ResourceType> RequestBuilder<ResourceType> as(
@NonNull Class<ResourceType> resourceClass) {
// resourceClass 就是最終要轉(zhuǎn)碼的類型
return new RequestBuilder<>(glide, this, resourceClass, context);
}
}
適配不同資源的加載焚辅,load有多個重載方法,他們最終都通過as方法來獲取一個RequestBuilder對象苟鸯,后面一連串的鏈式調(diào)用同蜻,都將通過這個對象的方法作為入口來執(zhí)行。和RequestManager 的load方法一樣早处,RequestBuilder的load也有許多重載方法湾蔓,我們以網(wǎng)絡(luò)地址加載為例來做分析掌实。
public class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBuilder<TranscodeType>>
implements Cloneable,
ModelTypes<RequestBuilder<TranscodeType>> {
private Object model;
private boolean isModelSet;
//加載網(wǎng)絡(luò)地址
public RequestBuilder<TranscodeType> load(@Nullable String string) {
return loadGeneric(string);
}
//將地址封裝成model
private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
this.model = model;
isModelSet = true;
return this;
}
}
在執(zhí)行請求前拱层,所有數(shù)據(jù)源都會被封裝成一個model對象碎绎,它是Object類型的度硝。
load方法調(diào)用完成肝谭,便獲得的一個RequestBuilder對象二跋,接著通過它調(diào)用into方法裆站。
public class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBuilder<TranscodeType>>
implements Cloneable,
ModelTypes<RequestBuilder<TranscodeType>> {
......
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
Util.assertMainThread();
Preconditions.checkNotNull(view);
BaseRequestOptions<?> requestOptions = this;
if (!requestOptions.isTransformationSet()
&& requestOptions.isTransformationAllowed()
&& view.getScaleType() != null) {
// 根據(jù)裁剪配置options
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:
}
}
return into(
glideContext.buildImageViewTarget(view, transcodeClass),
null,
requestOptions,
Executors.mainThreadExecutor());
}
}
會根據(jù)我們在ImageView中設(shè)置的ScaleType類型溯职,給requestOptions 配置裁剪類型烂瘫。最后的into重載方法中媒熊,將調(diào)用buildImageViewTarget根據(jù)轉(zhuǎn)碼的類型來生成一個 ViewTarget,這個方法定義在GlideContext中坟比。
public class GlideContext extends ContextWrapper {
......
private final ImageViewTargetFactory imageViewTargetFactory;
......
public <X> ViewTarget<ImageView, X> buildImageViewTarget(
@NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {
return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
}
}
在上一篇分析Glide的初始化時芦鳍,ImageViewTargetFactory 這個圖片顯示目標對象工廠,已經(jīng)在構(gòu)造方法中創(chuàng)建出來了温算,同時還創(chuàng)建了GlideContext 對象怜校,將ImageViewTargetFactory 傳遞給它。
public class ImageViewTargetFactory {
@NonNull
@SuppressWarnings("unchecked")
public <Z> ViewTarget<ImageView, Z> buildTarget(@NonNull ImageView view,
@NonNull Class<Z> clazz) {
//Bitmap
if (Bitmap.class.equals(clazz)) {
return (ViewTarget<ImageView, Z>) new BitmapImageViewTarget(view);
//是否Drawable或其子類
} 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)");
}
}
}
ViewTarget的子類有兩種注竿,在上面的RequestManager 類中雖然有多個as方法茄茁,但最終的轉(zhuǎn)碼類型只會有兩類,即Bitmap類型或Drawable及其子類類型巩割,我們加載網(wǎng)絡(luò)地址裙顽,這里的ViewTarget將使用DrawableImageViewTarget,它繼承ImageViewTarget宣谈,持有ImageView對象愈犹。
public class DrawableImageViewTarget extends ImageViewTarget<Drawable> {
public DrawableImageViewTarget(ImageView view) {
super(view);
}
@SuppressWarnings({"unused", "deprecation"})
@Deprecated
public DrawableImageViewTarget(ImageView view, boolean waitForLayout) {
super(view, waitForLayout);
}
//設(shè)置圖片
@Override
protected void setResource(@Nullable Drawable resource) {
view.setImageDrawable(resource);
}
}
看到setResource這個方法我們可以猜到,最終圖片被顯示到ImageView中,將通過它來完成漩怎。我們先回到RequestManager 重載的into方法勋颖。
public class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBuilder<TranscodeType>>
implements Cloneable,
ModelTypes<RequestBuilder<TranscodeType>> {
private <Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener,
BaseRequestOptions<?> options,
Executor callbackExecutor) {
//這里的Target就是DrawableImageViewTarget了
Preconditions.checkNotNull(target);
//是否設(shè)置了數(shù)據(jù)源,也就是url勋锤,在load中isModelSet已置為true
if (!isModelSet) {
throw new IllegalArgumentException("You must call #load() before calling #into()");
}
//Request類是一個接口饭玲,他抽象了Glide加載圖片請求
Request request = buildRequest(target, targetListener, options, callbackExecutor);
//獲取上一次的Request
Request previous = target.getRequest();
// 當前的target里有Request存在
if (request.isEquivalentTo(previous)
&& !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
//回收剛新建的Request對象
request.recycle();
if (!Preconditions.checkNotNull(previous).isRunning()) {
//執(zhí)行當前的Request
previous.begin();
}
//結(jié)束
return target;
}
//清除target
requestManager.clear(target);
//Target中設(shè)置request
target.setRequest(request);
//執(zhí)行request
requestManager.track(target, request);
return target;
}
}
Request用來發(fā)出加載圖片的請求,通過buildRequest來構(gòu)建叁执,然后將通過RequestManager對象來執(zhí)行這個請求茄厘。我們先看構(gòu)建過程。
public class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBuilder<TranscodeType>>
implements Cloneable,
ModelTypes<RequestBuilder<TranscodeType>> {
private Request buildRequest(
Target<TranscodeType> target,
@Nullable RequestListener<TranscodeType> targetListener,
BaseRequestOptions<?> requestOptions,
Executor callbackExecutor) {
return buildRequestRecursive(
target,
targetListener,
null,
transitionOptions,
requestOptions.getPriority(),
requestOptions.getOverrideWidth(),
requestOptions.getOverrideHeight(),
requestOptions,
callbackExecutor);
}
private Request buildRequestRecursive(
Target<TranscodeType> target,
@Nullable RequestListener<TranscodeType> targetListener,
@Nullable RequestCoordinator parentCoordinator,
TransitionOptions<?, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight,
BaseRequestOptions<?> requestOptions,
Executor callbackExecutor) {
// 如果配置了錯誤請求則新建錯誤請求協(xié)調(diào)器
ErrorRequestCoordinator errorRequestCoordinator = null;
if (errorBuilder != null) {
errorRequestCoordinator = new ErrorRequestCoordinator(parentCoordinator);
parentCoordinator = errorRequestCoordinator;
}
// 構(gòu)造目標請求
Request mainRequest =
buildThumbnailRequestRecursive(
target,
targetListener,
parentCoordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
requestOptions,
callbackExecutor);
//如果沒有配置錯誤請求則結(jié)束谈宛,否則繼續(xù)下面代碼構(gòu)建錯誤時的備用請求
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(
target,
targetListener,
errorRequestCoordinator,
errorBuilder.transitionOptions,
errorBuilder.getPriority(),
errorOverrideWidth,
errorOverrideHeight,
errorBuilder,
callbackExecutor);
errorRequestCoordinator.setRequests(mainRequest, errorRequest);
return errorRequestCoordinator;
}
private Request buildThumbnailRequestRecursive(
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()");
}
// 設(shè)置 transitionOptions
TransitionOptions<?, ? super TranscodeType> thumbTransitionOptions =
thumbnailBuilder.transitionOptions;
if (thumbnailBuilder.isDefaultTransitionOptionsSet) {
thumbTransitionOptions = transitionOptions;
}
//優(yōu)先級
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();
}
// 縮略圖請求協(xié)調(diào)器
ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
// 目標請求
Request fullRequest =
obtainRequest(
target,
targetListener,
requestOptions,
coordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
callbackExecutor);
isThumbnailBuilt = true;
// 縮略圖的請求
Request thumbRequest =
thumbnailBuilder.buildRequestRecursive(
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(parentCoordinator);
Request fullRequest =
obtainRequest(
target,
targetListener,
requestOptions,
coordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
callbackExecutor);
BaseRequestOptions<?> thumbnailOptions =
requestOptions.clone().sizeMultiplier(thumbSizeMultiplier);
Request thumbnailRequest =
obtainRequest(
target,
targetListener,
thumbnailOptions,
coordinator,
transitionOptions,
getThumbnailPriority(priority),
overrideWidth,
overrideHeight,
callbackExecutor);
coordinator.setRequests(fullRequest, thumbnailRequest);
return coordinator;
} else {
// 沒有縮略圖時次哈,構(gòu)造請求
return obtainRequest(
target,
targetListener,
requestOptions,
parentCoordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
callbackExecutor);
}
}
private Request obtainRequest(
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,
model,
transcodeClass,
requestOptions,
overrideWidth,
overrideHeight,
priority,
target,
targetListener,
requestListeners,
requestCoordinator,
glideContext.getEngine(),
transitionOptions.getTransitionFactory(),
callbackExecutor);
}
}
構(gòu)建目標Request請求的代碼比較長,如果我們配置了縮略圖要求吆录,它將構(gòu)建縮略圖請求窑滞,并和目標請求一起放入到協(xié)調(diào)器中。ThumbnailRequestCoordinator 請求協(xié)調(diào)器径筏,可以用來協(xié)調(diào)各請求的順序葛假。
我們只分析目標請求流程障陶,也就是沒有設(shè)置縮略圖的情況滋恬。由obtain靜態(tài)方法可以看到,最終獲得的目標Request對象就是SingleRequest抱究,它封裝了圖片請求需要的各個成員恢氯。
public final class SingleRequest<R> implements Request,
SizeReadyCallback,
ResourceCallback,
FactoryPools.Poolable {
public static <R> SingleRequest<R> obtain(
Context context,
GlideContext glideContext,
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) {
@SuppressWarnings("unchecked") SingleRequest<R> request =
(SingleRequest<R>) POOL.acquire();
//創(chuàng)建SingleRequest對象
if (request == null) {
request = new SingleRequest<>();
}
//初始化
request.init(
context,
glideContext,
model,
transcodeClass,
requestOptions,
overrideWidth,
overrideHeight,
priority,
target,
targetListener,
requestListeners,
requestCoordinator,
engine,
animationFactory,
callbackExecutor);
return request;
}
//賦值成員變量
private synchronized void init(
Context context,
GlideContext glideContext,
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) {
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.isLoggingRequestOriginsEnabled()) {
requestOrigin = new RuntimeException("Glide request origin trace");
}
}
}
目標Request已經(jīng)構(gòu)建完成,再回到requestManager.track(target, request)這行代碼鼓寺,看Request如何被發(fā)出去的勋拟。它通過RequestManager來調(diào)用。
public class RequestManager implements LifecycleListener,
ModelTypes<RequestBuilder<Drawable>> {
//請求追蹤器
private final RequestTracker requestTracker;
public RequestManager(
@NonNull Glide glide, @NonNull Lifecycle lifecycle,
@NonNull RequestManagerTreeNode treeNode, @NonNull Context context) {
this(
glide,
lifecycle,
treeNode,
new RequestTracker(),//創(chuàng)建請求追蹤器
glide.getConnectivityMonitorFactory(),
context);
}
synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
targetTracker.track(target);
// 開始請求
requestTracker.runRequest(request);
}
}
任務(wù)被移交給了RequestTracker請求追蹤器進行追蹤妈候,這個對象RequestManager在構(gòu)造時創(chuàng)建的敢靡。
public class RequestTracker {
private final Set<Request> requests =
Collections.newSetFromMap(new WeakHashMap<Request, Boolean>());
private final List<Request> pendingRequests = new ArrayList<>();
private boolean isPaused;
//執(zhí)行請求任務(wù)
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);
}
}
如果任務(wù)此時被暫停了,那么將清理掉某些資源苦银,但這個Request 還可以通過begin()方法來重新發(fā)出啸胧,所以被保存到pendingRequests待處理
列表中。
上面說過幔虏,所有圖片請求相關(guān)的成員都被封裝到Request(SingleRequest )對象中纺念,它將指定Target去加載自己的資源。
public final class SingleRequest<R> implements Request,
SizeReadyCallback,
ResourceCallback,
FactoryPools.Poolable {
public synchronized void begin() {
assertNotCallingCallbacks();
stateVerifier.throwIfRecycled();
startTime = LogTime.getLogTime();
//即地址為null
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");
}
// 請求加載完成后回調(diào)
if (status == Status.COMPLETE) {
onResourceReady(resource, DataSource.MEMORY_CACHE);
return;
}
status = Status.WAITING_FOR_SIZE;
// 如果指定了寬高想括,直接回調(diào) onSizeReady
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
onSizeReady(overrideWidth, overrideHeight);
} else {
// 根據(jù) target 的寬高來加載圖片的寬高
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));
}
}
public synchronized void onSizeReady(int width, int height) {
stateVerifier.throwIfRecycled();
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));
}
//加載圖片并返回狀態(tài)
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));
}
}
}
加載分兩種情況,如果指定了一個固定的寬高瑟蜈,就會直接執(zhí)行onSizeReady()方法烟逊。如果沒指定的話渣窜,調(diào)用target.getSize()方法。這個target.getSize()方法宪躯,它會根據(jù)ImageView布局設(shè)置的寬高图毕,算出圖片應(yīng)該顯示的寬高。計算完之后眷唉,它也會調(diào)用onSizeReady()方法予颤。
但請求加載流程還不是在這個類中執(zhí)行的,它把這個任務(wù)交給了Engine對象來處理冬阳,這個對象是在GlideBuilder的build方法中創(chuàng)建的蛤虐,我們前面分析過,在build方法中還創(chuàng)建了幾個緩存池和以及復用池肝陪,這些池子都封裝到了Engine對象中驳庭。并且在隨后的Glide構(gòu)造方法中構(gòu)建GlideContext對象時,將其保存到這個上下文中氯窍。
public class Engine implements EngineJobListener,
MemoryCache.ResourceRemovedListener,
EngineResource.ResourceListener {
public synchronized <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;
// 創(chuàng)建資源索引 KEY
EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations,
resourceClass, transcodeClass, options);
//從緩存中取
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;
}
//從緩存中獲取
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;
}
// 獲取已經(jīng)存在的加載任務(wù) 饲常,onlyRetrieveFromCache 參數(shù)表示是否只加載緩存中的數(shù)據(jù)
EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
if (current != null) {
// 添加 SingleRequest 回調(diào)對象
current.addCallback(cb, callbackExecutor);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Added to existing load", startTime, key);
}
return new LoadStatus(cb, current);
}
// 構(gòu)造 EngineJob 對象,用于啟動解碼任務(wù)
EngineJob<R> engineJob =
engineJobFactory.build(
key,
isMemoryCacheable,
useUnlimitedSourceExecutorPool,
useAnimationPool,
onlyRetrieveFromCache);
//構(gòu)建解碼器并初始化
DecodeJob<R> decodeJob =
decodeJobFactory.build(
glideContext,
model,
key,
signature,
width,
height,
resourceClass,
transcodeClass,
priority,
diskCacheStrategy,
transformations,
isTransformationRequired,
isScaleOnlyOrNoTransform,
onlyRetrieveFromCache,
options,
engineJob);
// 緩存加載任務(wù)
jobs.put(key, engineJob);
// 添加 SingleRequest 回調(diào)對象
engineJob.addCallback(cb, callbackExecutor);
// 執(zhí)行解碼任務(wù)
engineJob.start(decodeJob);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Started new load", startTime, key);
}
return new LoadStatus(cb, engineJob);
}
}
既然Engine 封裝了許多緩存池狼讨,那么做網(wǎng)絡(luò)請求前贝淤,必然先看緩存有沒有。buildKey方法將幾個參數(shù)封裝成EngineKey 政供,根據(jù)這個Key 來獲取內(nèi)存緩存數(shù)據(jù)播聪,如果存在,則直接回調(diào)成功布隔,如果不存在离陶,則新建EngineJob 對象和DecodeJob解碼器,DecodeJob實現(xiàn)了Runnable衅檀,通過EngineJob 對象調(diào)用start來啟動招刨。
緩存的獲取這里先不分析,我們分析首次加載哀军,即沒有緩存的情況沉眶。那么,緊接著的工作又傳遞給了EngineJob 對象排苍,它會通過線程池來開啟DecodeJob這個Runnable沦寂。
class EngineJob<R> implements DecodeJob.Callback<R>,
Poolable {
//通過線程池啟動圖片加載任務(wù)
public synchronized void start(DecodeJob<R> decodeJob) {
this.decodeJob = decodeJob;
GlideExecutor executor = decodeJob.willDecodeFromCache()
? diskCacheExecutor
: getActiveSourceExecutor();
executor.execute(decodeJob);
}
}
很顯然,GlideExecutor 是Glide自定義的Executor淘衙,它內(nèi)部實現(xiàn)了線程池传藏。因此,我們直接看DecodeJob的run方法。
class DecodeJob<R> implements DataFetcherGenerator.FetcherReadyCallback,
Runnable,
Comparable<DecodeJob<?>>,
Poolable {
//加載輔助類
private final DecodeHelper<R> decodeHelper = new DecodeHelper<>();
DecodeJob<R> init(
GlideContext glideContext,
Object model,
EngineKey loadKey,
Key signature,
int width,
int height,
Class<?> resourceClass,
Class<R> transcodeClass,
Priority priority,
DiskCacheStrategy diskCacheStrategy,
Map<Class<?>, Transformation<?>> transformations,
boolean isTransformationRequired,
boolean isScaleOnlyOrNoTransform,
boolean onlyRetrieveFromCache,
Options options,
Callback<R> callback,
int order) {
decodeHelper.init(
glideContext,
model,
signature,
width,
height,
diskCacheStrategy,
resourceClass,
transcodeClass,
priority,
options,
transformations,
isTransformationRequired,
isScaleOnlyOrNoTransform,
diskCacheProvider);
this.glideContext = glideContext;
this.signature = signature;
this.priority = priority;
this.loadKey = loadKey;
this.width = width;
this.height = height;
this.diskCacheStrategy = diskCacheStrategy;
this.onlyRetrieveFromCache = onlyRetrieveFromCache;
this.options = options;
this.callback = callback;
this.order = order;
this.runReason = RunReason.INITIALIZE;//初始化RunReason為INITIALIZE
this.model = model;
return this;
}
public void run() {
GlideTrace.beginSectionFormat("DecodeJob#run(model=%s)", model);
DataFetcher<?> localFetcher = currentFetcher;
try {
if (isCancelled) {
notifyFailed();
return;
}
//進入runWrapped
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();
}
}
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);
}
}
//獲取不同類型加載器
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);
}
}
//根據(jù)不同加載器獲取圖片
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();
}
}
}
在DecodeJob被構(gòu)造和初始化時毯侦,RunReason設(shè)置為INITIALIZE哭靖,也就是說,runWrapped進入了INITIALIZE這個case侈离,如代碼所示试幽,有處理過的緩存資源加載器、原始圖片資源緩存加載器和遠程圖片資源加載器3種不同類型的加載器卦碾,會根據(jù)當前的狀態(tài)決定使用哪一個铺坞,由于是首次加載,因此洲胖,將獲取到遠程圖片資源加載器济榨,即SourceGenerator這個對象。
runGenerators方法內(nèi)是一個while遞歸循環(huán)绿映,它通過加載器的startNext方法來執(zhí)行加載的任務(wù)擒滑,開啟成功結(jié)束循環(huán),不再尋找新的加載器叉弦。
class SourceGenerator implements DataFetcherGenerator,
DataFetcher.DataCallback<Object>,
DataFetcherGenerator.FetcherReadyCallback {
private final DecodeHelper<?> helper;
private volatile ModelLoader.LoadData<?> loadData;
public boolean startNext() {
//判斷是否有緩存
if (dataToCache != null) {
Object data = dataToCache;
dataToCache = null;
// 緩存數(shù)據(jù)
cacheData(data);
}
if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {
return true;
}
sourceCacheGenerator = null;
// 沒有緩存丐一,從遠程加載
loadData = null;
boolean started = false;
// 遍歷所有的ModelLoader模塊加載器
while (!started && hasNextModelLoader()) {
//拿到 HttpGlideUrlLoader 對象
loadData = helper.getLoadData().get(loadDataListIndex++);
if (loadData != null
&& (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
|| helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
started = true;
// 調(diào)用 HttpUrlFetcher 的 loadData 方法
loadData.fetcher.loadData(helper.getPriority(), this);
}
}
return started;
}
}
DecodeHelper是在Engine中構(gòu)建的,使用getLoadData獲取到ModelLoader的列表淹冰。
final class DecodeHelper<Transcode> {
//獲取List<LoadData<?>>
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為HttpGlideUrlLoader
ModelLoader<Object, ?> modelLoader = modelLoaders.get(i);
//構(gòu)建LoadData
LoadData<?> current =
modelLoader.buildLoadData(model, width, height, options);
if (current != null) {
loadData.add(current);
}
}
}
return loadData;
}
}
這里獲取到ModelLoader為HttpGlideUrlLoader類型的库车,通過buildLoadData構(gòu)建一個ModelLoader.LoadData對象。
public class HttpGlideUrlLoader implements ModelLoader<GlideUrl, InputStream> {
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);
//構(gòu)建HttpUrlFetcher將它傳遞給LoadData
return new LoadData<>(url, new HttpUrlFetcher(url, timeout));
}
}
因此榄棵,上面loadData.fetcher.loadData代碼就是在HttpUrlFetcher中執(zhí)行的凝颇。
public class HttpUrlFetcher implements DataFetcher<InputStream> {
@Override
public void loadData(@NonNull Priority priority,
@NonNull DataCallback<? super InputStream> callback) {
long startTime = LogTime.getLogTime();
// 調(diào)用 loadDataWithRedirects 方法執(zhí)行網(wǎng)絡(luò)請求
try {
InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
//將輸入流回調(diào)給DataCallback
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));
}
}
}
//執(zhí)行網(wǎng)絡(luò)請求
private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl,
Map<String, String> headers) throws IOException {
if (redirects >= MAXIMUM_REDIRECTS) {
throw new HttpException("Too many (> " + MAXIMUM_REDIRECTS + ") redirects!");
} else {
try {
if (lastUrl != null && url.toURI().equals(lastUrl.toURI())) {
throw new HttpException("In re-direct loop");
}
} catch (URISyntaxException e) {
}
}
//根據(jù)url構(gòu)建Connection
urlConnection = connectionFactory.build(url);
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);
urlConnection.setInstanceFollowRedirects(false);
//請求下載
urlConnection.connect();
//先將輸入流保存
stream = urlConnection.getInputStream();
//如果沒有突然被取消
if (isCancelled) {
return null;
}
//狀態(tài)碼
final int statusCode = urlConnection.getResponseCode();
//狀態(tài)碼為200潘拱,將輸入流返回
if (isHttpOk(statusCode)) {
return getStreamForSuccessfulRequest(urlConnection);
} else if (isHttpRedirect(statusCode)) {
String redirectUrlString = urlConnection.getHeaderField("Location");
if (TextUtils.isEmpty(redirectUrlString)) {
throw new HttpException("Received empty or null redirect url");
}
URL redirectUrl = new URL(url, redirectUrlString);
cleanup();
return loadDataWithRedirects(redirectUrl, redirects + 1, url, headers);
} else if (statusCode == INVALID_STATUS_CODE) {
throw new HttpException(statusCode);
} else {
throw new HttpException(urlConnection.getResponseMessage(), statusCode);
}
}
//獲取輸入流
private InputStream getStreamForSuccessfulRequest(HttpURLConnection urlConnection)
throws IOException {
if (TextUtils.isEmpty(urlConnection.getContentEncoding())) {
int contentLength = urlConnection.getContentLength();
stream = ContentLengthInputStream.obtain(urlConnection.getInputStream(), contentLength);
} else {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Got non empty content encoding: " + urlConnection.getContentEncoding());
}
stream = urlConnection.getInputStream();
}
return stream;
}
//狀態(tài)碼為200
private static boolean isHttpOk(int statusCode) {
return statusCode / 100 == 2;
}
}
分析到這疹鳄,總算看到網(wǎng)絡(luò)請求的調(diào)用了。如果狀態(tài)為200芦岂,那么將獲取得數(shù)據(jù)輸入流瘪弓,回調(diào)給DataCallback接口,它是從loadData方法傳遞進來的禽最,再回頭loadData的調(diào)用知道腺怯,它其實就是SourceGenerator對象。
class SourceGenerator implements DataFetcherGenerator,
DataFetcher.DataCallback<Object>,
DataFetcherGenerator.FetcherReadyCallback {
private final FetcherReadyCallback cb;
private final DecodeHelper<?> helper;
//緩存流
private Object dataToCache;
SourceGenerator(DecodeHelper<?> helper, FetcherReadyCallback cb) {
this.helper = helper;
this.cb = cb;
}
@Override
public void onDataReady(Object data) {
DiskCacheStrategy diskCacheStrategy = helper.getDiskCacheStrategy();
//如果設(shè)置了磁盤緩存
if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) {
//將數(shù)據(jù)流緩存到磁盤對象中
dataToCache = data;
// 重啟 DecodeJob 任務(wù)
cb.reschedule();
} else {
//沒有緩存川无,回調(diào)給DecodeJob
cb.onDataFetcherReady(loadData.sourceKey, data, loadData.fetcher,
loadData.fetcher.getDataSource(), originalKey);
}
}
}
Glide認為遠程網(wǎng)絡(luò)圖片獲取是昂貴的呛占,所以默認情況下網(wǎng)絡(luò)圖片會緩存原圖,但本地圖片懦趋,包括drawable/assets等不會緩存原圖晾虑。
有沒有緩存,最終都會調(diào)用到onDataFetcherReady這個方法。與沒有緩存相比帜篇,有緩存流程上的區(qū)別是糙捺,會將數(shù)據(jù)流緩存到磁盤中,然后開一個新的線程笙隙,再通過另一個緩存加載器處理洪灯,并獲取數(shù)據(jù)流。以上說過竟痰,默認是有緩存原圖的签钩,因此,我們先分析緩存的調(diào)用流程坏快。
在這里提一下边臼,整個流程的調(diào)用就類似一個命令下發(fā),這個命令會一層層往下傳遞假消,傳給到最后一棒的對象去取得數(shù)據(jù)柠并,再沿著原來的路線,將完成的數(shù)據(jù)富拗,一層層往回傳臼予。這一點務(wù)必記住,后面的流程都是在一邊處理數(shù)據(jù)啃沪,一邊向之前的對象傳遞粘拾,直至傳給SingleRequest這個對象里的Target成員,來顯示圖片创千。
因此缰雇,這里就開始了往前的傳遞,調(diào)用reschedule的對象為DecodeJob追驴。
class DecodeJob<R> implements DataFetcherGenerator.FetcherReadyCallback,
Runnable,
Comparable<DecodeJob<?>>,
Poolable {
@Override
public void reschedule() {
//RunReason被置為SWITCH_TO_SOURCE_SERVICE
runReason = RunReason.SWITCH_TO_SOURCE_SERVICE;
//回調(diào)給EngineJob
callback.reschedule(this);
}
RunReason被置為SWITCH_TO_SOURCE_SERVICE械哟。緊接著再次往回通知EngineJob對象。
class EngineJob<R> implements DecodeJob.Callback<R>,
Poolable {
@Override
public void reschedule(DecodeJob<?> job) {
getActiveSourceExecutor().execute(job);
}
}
重新開啟線程殿雪,執(zhí)行DecodeJob這個任務(wù)暇咆。這回直接執(zhí)行runGenerators方法,再次調(diào)用SourceGenerator的startNext方法丙曙,此時緩存就不為null了爸业。
class SourceGenerator implements DataFetcherGenerator,
DataFetcher.DataCallback<Object>,
DataFetcherGenerator.FetcherReadyCallback {
//緩存流
private Object dataToCache;
//緩存加載器
private DataCacheGenerator sourceCacheGenerator;
@Override
public boolean startNext() {
//緩存不為null
if (dataToCache != null) {
Object data = dataToCache;
dataToCache = null;
cacheData(data);
}
//此時sourceCacheGenerator 不為null
if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {
return true;
}
......
}
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);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Finished encoding source to cache"
+ ", key: " + originalKey
+ ", data: " + dataToCache
+ ", encoder: " + encoder
+ ", duration: " + LogTime.getElapsedMillis(startTime));
}
} finally {
loadData.fetcher.cleanup();
}
//構(gòu)建緩存加載器來處理
sourceCacheGenerator =
new DataCacheGenerator(Collections.singletonList(loadData.sourceKey), helper, this);
}
dataToCache 將不再是 null ,所以會將數(shù)據(jù)緩存到本地硬盤亏镰,并啟動另一個加載器DataCacheGenerator扯旷,這個加載器正是用來加載緩存在本地的圖片的。它賦值給了成員變量sourceCacheGenerator 索抓,隨后執(zhí)行其startNext方法钧忽。
DataCacheGenerator和ResourceCacheGenerator這兩個加載器跟SourceGenerator類似某抓,只不過根據(jù)不同情形的圖片進行加載:
- DataCacheGenerator:用于加載原始圖片。
- ResourceCacheGenerator:用于加載處理過的圖片惰瓜。
- SourceGenerator:用于加載網(wǎng)絡(luò)圖片否副。
因此,數(shù)據(jù)從緩存中加載成功崎坊,同樣回傳給DataCacheGenerator的 onDataReady方法备禀。
class DataCacheGenerator implements DataFetcherGenerator,
DataFetcher.DataCallback<Object> {
public void onDataReady(Object data) {
cb.onDataFetcherReady(sourceKey, data, loadData.fetcher, DataSource.DATA_DISK_CACHE, sourceKey);
}
}
前面我們提到過,有沒有緩存奈揍,最終都會調(diào)用DecodeJob的onDataFetcherReady方法曲尸,因為它是用來解碼的。
class DecodeJob<R> implements DataFetcherGenerator.FetcherReadyCallback,
Runnable,
Comparable<DecodeJob<?>>,
Poolable {
@Override
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;
if (Thread.currentThread() != currentThread) {
runReason = RunReason.DECODE_DATA;
callback.reschedule(this);
} else {
GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData");
try {
//解碼數(shù)據(jù)
decodeFromRetrievedData();
} finally {
GlideTrace.endSection();
}
}
//解碼獲取Resource
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 {
//解碼得到LazyBitmapDrawableResource
resource = decodeFromData(currentFetcher, currentData, currentDataSource);
} catch (GlideException e) {
e.setLoggingDetails(currentAttemptingKey, currentDataSource);
throwables.add(e);
}
//進行編碼輸出
if (resource != null) {
notifyEncodeAndRelease(resource, currentDataSource);
} else {
runGenerators();
}
}
private <Data> Resource<R> decodeFromData(DataFetcher<?> fetcher, Data data,
DataSource dataSource) throws GlideException {
try {
if (data == null) {
return null;
}
long startTime = LogTime.getLogTime();
//從DecodeHelper中獲取LoadPath對象
Resource<R> result = decodeFromFetcher(data, dataSource);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Decoded result " + result, startTime);
}
return result;
} finally {
fetcher.cleanup();
}
}
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 {
//使用LoadPath進行解碼
return path.load(
rewinder, options, width, height, new DecodeCallback<ResourceType>(dataSource));
} finally {
rewinder.cleanup();
}
}
}
解碼的流程最終是通過LoadPath這個對象來進行處理的男翰。它是根據(jù)傳入的處理數(shù)據(jù)另患,來返回特定的數(shù)據(jù)解碼處理器對象。
public class LoadPath<Data, ResourceType, Transcode> {
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;
//遍歷從列表獲取DecodePath進行解碼
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;
}
}
DecodePath類還并不是最終的解碼器蛾绎,它只是封裝解碼和轉(zhuǎn)碼的工具昆箕,它本身不做解碼轉(zhuǎn)碼的具體操作。
public class DecodePath<DataType, ResourceType, Transcode> {
//轉(zhuǎn)碼器
private final ResourceTranscoder<ResourceType, Transcode> transcoder;
public Resource<Transcode> decode(DataRewinder<DataType> rewinder, int width, int height,
@NonNull Options options, DecodeCallback<ResourceType> callback) throws GlideException {
// 返回的可能是 BitmapResource 對象租冠,看具體類型
Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);
// 回調(diào) DecodeJob 的 onResourceDecoded 方法鹏倘,返回需要轉(zhuǎn)碼的類型
Resource<ResourceType> transformed = callback.onResourceDecoded(decoded);
//轉(zhuǎn)碼 BitmapResource,返回 LazyBitmapDrawableResource
return transcoder.transcode(transformed, options);
}
private Resource<ResourceType> decodeResourceWithList(DataRewinder<DataType> rewinder, int width,
int height, @NonNull Options options, List<Throwable> exceptions) throws GlideException {
Resource<ResourceType> result = null;
//遍歷獲取StreamBitmapDecoder
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();
//解碼成Drawable
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;
}
}
這里需要的是 Drawable 類型顽爹,所以纤泵,decodeResource方法最終會通過 StreamBitmapDecoder將數(shù)據(jù)流解碼成一個 BitmapResource 對象。再通過ResourceTranscoder轉(zhuǎn)碼器镜粤,它是BitmapDrawableTranscoder類型的捏题,轉(zhuǎn)碼為LazyBitmapDrawableResource對象。
public class BitmapDrawableTranscoder implements ResourceTranscoder<Bitmap, BitmapDrawable> {
private final Resources resources;
@SuppressWarnings("unused")
public BitmapDrawableTranscoder(@NonNull Context context) {
this(context.getResources());
}
@Deprecated
public BitmapDrawableTranscoder(
@NonNull Resources resources, @SuppressWarnings("unused") BitmapPool bitmapPool) {
this(resources);
}
public BitmapDrawableTranscoder(@NonNull Resources resources) {
this.resources = Preconditions.checkNotNull(resources);
}
//轉(zhuǎn)碼
@Override
public Resource<BitmapDrawable> transcode(@NonNull Resource<Bitmap> toTranscode,
@NonNull Options options) {
return LazyBitmapDrawableResource.obtain(resources, toTranscode);
}
}
public final class LazyBitmapDrawableResource implements Resource<BitmapDrawable>,
Initializable {
//獲取LazyBitmapDrawableResource對象
public static Resource<BitmapDrawable> obtain(
@NonNull Resources resources, @Nullable Resource<Bitmap> bitmapResource) {
if (bitmapResource == null) {
return null;
}
return new LazyBitmapDrawableResource(resources, bitmapResource);
}
//獲取BitmapDrawable
@Override
public BitmapDrawable get() {
return new BitmapDrawable(resources, bitmapResource.get());
}
}
這里注意到get方法返回了BitmapDrawable對象肉渴,它就是最終用來顯示到ImageView上的類型」現(xiàn)在解碼和轉(zhuǎn)碼工作已經(jīng)完成了。所以黄虱,數(shù)據(jù)繼續(xù)往回傳遞通知上層稚矿,將獲取到的結(jié)果進行展示。
因此捻浦,回到DecodeJob類的decodeFromRetrievedData方法內(nèi)部,調(diào)用notifyEncodeAndRelease 繼續(xù)往下執(zhí)行桥爽。
class DecodeJob<R> implements DataFetcherGenerator.FetcherReadyCallback,
Runnable,
Comparable<DecodeJob<?>>,
Poolable {
private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {
if (resource instanceof Initializable) {
((Initializable) resource).initialize();
}
//將資源鎖定
Resource<R> result = resource;
LockedResource<R> lockedResource = null;
if (deferredEncodeManager.hasResourceToEncode()) {
lockedResource = LockedResource.obtain(resource);
result = lockedResource;
}
//通知上層任務(wù)完成
notifyComplete(result, dataSource);
stage = Stage.ENCODE;
try {
if (deferredEncodeManager.hasResourceToEncode()) {
deferredEncodeManager.encode(diskCacheProvider, options);
}
} finally {
if (lockedResource != null) {
lockedResource.unlock();
}
}
onEncodeComplete();
}
private void notifyComplete(Resource<R> resource, DataSource dataSource) {
setNotifiedOrThrow();
//回調(diào)給EngineJob
callback.onResourceReady(resource, dataSource);
}
}
LazyBitmapDrawableResource數(shù)據(jù)繼續(xù)往回傳給EngineJob類朱灿。它還會繼續(xù)往上傳給SingleRequest類。
class EngineJob<R> implements DecodeJob.Callback<R>,
Poolable {
//這是LazyBitmapDrawableResource
private Resource<?> resource;
@Override
public void onResourceReady(Resource<R> resource, DataSource dataSource) {
//保存數(shù)據(jù)
synchronized (this) {
this.resource = resource;
this.dataSource = dataSource;
}
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");
}
//構(gòu)建EngineResource
engineResource = engineResourceFactory.build(resource, isCacheable);
hasResource = true;
copy = cbs.copy();
incrementPendingCallbacks(copy.size() + 1);
localKey = key;
localResource = engineResource;
}
listener.onEngineJobComplete(this, localKey, localResource);
//通過子線程回調(diào)
for (final ResourceCallbackAndExecutor entry : copy) {
entry.executor.execute(new CallResourceReady(entry.cb));
}
decrementPendingCallbacks();
}
private class CallResourceReady implements Runnable {
private final ResourceCallback cb;
CallResourceReady(ResourceCallback cb) {
this.cb = cb;
}
@Override
public void run() {
synchronized (EngineJob.this) {
if (cbs.contains(cb)) {
engineResource.acquire();
//調(diào)用callCallbackOnResourceReady傳遞給SingleRequest
callCallbackOnResourceReady(cb);
removeCallback(cb);
}
decrementPendingCallbacks();
}
}
}
@SuppressWarnings("WeakerAccess")
@Synthetic
synchronized void callCallbackOnResourceReady(ResourceCallback cb) {
try {
//調(diào)用SingleRequest的onResourceReady方法
cb.onResourceReady(engineResource, dataSource);
} catch (Throwable t) {
throw new CallbackException(t);
}
}
}
EngineJob構(gòu)建了一個EngineResource钠四,將LazyBitmapDrawableResource封裝在它的內(nèi)部盗扒,然后開啟線程跪楞,將數(shù)據(jù)傳遞給了SingleRequest類。
public final class SingleRequest<R> implements Request,
SizeReadyCallback,
ResourceCallback,
FactoryPools.Poolable {
@Override
public synchronized void onResourceReady(Resource<?> resource, DataSource dataSource) {
stateVerifier.throwIfRecycled();
loadStatus = null;
if (resource == null) {
GlideException exception = new GlideException("Expected to receive a Resource<R> with an "
+ "object of " + transcodeClass + " inside, but instead got null.");
onLoadFailed(exception);
return;
}
從EngineResource中獲取BitmapDrawable對象
Object received = resource.get();
if (received == null || !transcodeClass.isAssignableFrom(received.getClass())) {
releaseResource(resource);
GlideException exception = new GlideException("Expected to receive an object of "
+ transcodeClass + " but instead" + " got "
+ (received != null ? received.getClass() : "") + "{" + received + "} inside" + " "
+ "Resource{" + resource + "}."
+ (received != null ? "" : " " + "To indicate failure return a null Resource "
+ "object, rather than a Resource object containing null data."));
onLoadFailed(exception);
return;
}
if (!canSetResource()) {
releaseResource(resource);
status = Status.COMPLETE;
return;
}
//通知Target顯示圖片
onResourceReady((Resource<R>) resource, (R) received, dataSource);
}
private synchronized void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {
boolean isFirstResource = isFirstReadyResource();
status = Status.COMPLETE;
this.resource = resource;
if (glideContext.getLogLevel() <= Log.DEBUG) {
Log.d(GLIDE_TAG, "Finished loading " + result.getClass().getSimpleName() + " from "
+ dataSource + " for " + model + " with size [" + width + "x" + height + "] in "
+ LogTime.getElapsedMillis(startTime) + " ms");
}
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);
}
} finally {
isCallingCallbacks = false;
}
notifyLoadSuccess();
}
}
注意代碼中的resource.get()調(diào)用侣灶,這個resource是傳遞過來的EngineResource甸祭,上面說過,它已經(jīng)持有了LazyBitmapDrawableResource褥影,這個get方法池户,便會調(diào)用LazyBitmapDrawableResource的get方法獲取到BitmapDrawable對象,緊接著調(diào)用onResourceReady方法讓Target去展示圖片凡怎。
在最前面分析說過校焦,這個Target是ImageViewTarget的子類,BitmapImageViewTarget统倒。
public abstract class ImageViewTarget<Z> extends ViewTarget<ImageView, Z>
implements Transition.ViewAdapter {
@Override
public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {
if (transition == null || !transition.transition(resource, this)) {
//設(shè)置資源
setResourceInternal(resource);
} else {
maybeUpdateAnimatable(resource);
}
}
private void setResourceInternal(@Nullable Z resource) {
//調(diào)用子類方法
setResource(resource);
maybeUpdateAnimatable(resource);
}
protected abstract void setResource(@Nullable Z resource);
}
public class DrawableImageViewTarget extends ImageViewTarget<Drawable> {
public DrawableImageViewTarget(ImageView view) {
super(view);
}
@SuppressWarnings({"unused", "deprecation"})
@Deprecated
public DrawableImageViewTarget(ImageView view, boolean waitForLayout) {
super(view, waitForLayout);
}
//顯示圖片
@Override
protected void setResource(@Nullable Drawable resource) {
view.setImageDrawable(resource);
}
}
到此寨典,Glide整個圖片加載流程分析完畢。其中的into流程是最復雜的房匆,因為Glide做了大量的緩存處理和對象復用耸成。但整個基本調(diào)用流程是:下發(fā)一個Request后,通過網(wǎng)絡(luò)請求獲得數(shù)據(jù)浴鸿,進行解碼和轉(zhuǎn)碼墓猎,再沿路返回到Request類中,讓Target去做圖片展示赚楚。