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);
}
}