Glide源碼分析 – 啓動圖片加載流程
// 在 RequestBuilder.into()之前必須調用load()系列方法,設置model
// 重載的一系列into()方法最終都調用
/* private <Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener,
@NonNull RequestOptions options)
*/
Glide.with(context)
.load(url)
.apply(requestOptions)
.into(iv);
在這裏分析 參數是 imageView的 RequestBuilder.into(imageview)
① public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view)
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
Util.assertMainThread();
Preconditions.checkNotNull(view);
RequestOptions requestOptions = this.requestOptions;
if (!requestOptions.isTransformationSet()
&& requestOptions.isTransformationAllowed()
&& view.getScaleType() != null) {
// 創建縮放模式
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:
}
}
// glideContext.buildImageViewTarget(view, transcodeClass)
// 創建返回目標,根據
//Glide.with(context).asBitmap()
// Glide.with(context).asDrawable() 返回
/*
public <Z> ViewTarget<ImageView, Z> buildTarget(@NonNull ImageView view,
@NonNull Class<Z> clazz) {
if (Bitmap.class.equals(clazz)) {
return (ViewTarget<ImageView, Z>) new BitmapImageViewTarget(view);
} else if (Drawable.class.isAssignableFrom(clazz)) {
return (ViewTarget<ImageView, Z>) new DrawableImageViewTarget(view);
} else {
throw new IllegalArgumentException(
"Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
}
}
*/
return into(
glideContext.buildImageViewTarget(view, transcodeClass),
/*targetListener=*/ null,
requestOptions);
}
②進入 public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view)
private <Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener,
@NonNull RequestOptions options) {
Util.assertMainThread();
Preconditions.checkNotNull(target);
// 這裏表明 調用 into()之前必須調用load()設置model
if (!isModelSet) {
throw new IllegalArgumentException("You must call #load() before calling #into()");
}
options = options.autoClone();
// 創建本次請求對象,跟蹤發現最終調用SingleRequest.obtain()
// 返回 SingleRequest對象
Request request = buildRequest(target, targetListener, options);
// 獲取上次請求
Request previous = target.getRequest();
//如果本次請求與上次請求相同,並且未設置跳過內存緩存
if (request.isEquivalentTo(previous)
&& !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
// 回收本次請求
request.recycle();
//如果 previous 已經請求完畢,會返回false
if (!Preconditions.checkNotNull(previous).isRunning()) {
//使用 previous 去請求,如果有緩存會使用緩存
previous.begin();
}
return target;
}
//這裏會回收 target 的上次請求對象
requestManager.clear(target);
//給 target 設置本次請求的 request
target.setRequest(request);
//把請求塞入隊列,根據頁面是否在前臺,來處理請求
requestManager.track(target, request);
return target;
}
② 開始請求 Request.begin()
public void begin() {
...
...
// 尺寸有效
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
// 真正請求加載圖片
onSizeReady(overrideWidth, overrideHeight);
} else {
// 獲取尺寸,尺寸有效會回調 onSizeReady(overrideWidth, overrideHeight)
target.getSize(this);
}
}
// 這裏開始加載圖片
public void onSizeReady(int width, int height) {
...
// 引擎類開始加載
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);
}
③ Engine 開始執行圖片加載邏輯
public class Engine implements EngineJobListener, ... {
/* 弱引用實現 活動緩存
* activeResources 是Glide通過引用計數實現 Bitmap複用的關鍵
*/
private final ActiveResources activeResources;
/* 內存緩存 LruCache 實現
* LruCache 內部是一個 LinkedHashMap,使用LRU 最近最少訪問算法,淘汰緩存
*/
private final MemoryCache cache;
private final LazyDiskCacheProvider diskCacheProvider;//磁盤緩存
public <R> LoadStatus load(...) {
//到這裏還是主線程
Util.assertMainThread();
/* 根據請求信息(包括load(model)方法的參數、圖片寬高等),構建 key
* 這個key,也是用於 memoryCache diskCache 的key
*/
EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations,
resourceClass, transcodeClass, options);
//從 活動緩存 activeResources 去拿圖片
EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
if (active != null) {
//從活動緩存中找到圖片後,回調 onResourceReady() 方法
cb.onResourceReady(active, DataSource.MEMORY_CACHE);
...
return null;
}
/* 活動緩存 activeResources 中沒找到圖片
* 去內存緩存 cache 中獲取圖片
*/
EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
if (cached != null) {
//從內存緩存中找到圖片後,回調 onResourceReady() 方法
cb.onResourceReady(cached, DataSource.MEMORY_CACHE);
...
return null;
}
//根據key 獲取 EngineJob
EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
if (current != null) {
current.addCallback(cb);
...
return new LoadStatus(cb, current);
}
//構建 EngineJob
EngineJob<R> engineJob =
engineJobFactory.build(
key,
isMemoryCacheable,
useUnlimitedSourceExecutorPool,
useAnimationPool,
onlyRetrieveFromCache);
//構建 DecodeJob
DecodeJob<R> decodeJob =
decodeJobFactory.build(
glideContext,
model,
key,
signature,
width,
height,
resourceClass,
transcodeClass,
priority,
diskCacheStrategy,
transformations,
isTransformationRequired,
isScaleOnlyOrNoTransform,
onlyRetrieveFromCache,
options,
engineJob);
//根據key 緩存 EngineJob
jobs.put(key, engineJob);
engineJob.addCallback(cb);
engineJob.start(decodeJob);
...
return new LoadStatus(cb, engineJob);
}
}