Glide源码解析03-into#
最简单的Glide调用,如下所示,下面将根据Glide的调用顺序,进行源码解析。
Glide.with(this)
.load(uri)
.into(img);
into方法
在上一步load方法中,我们初始化了一些数据,并返回了GenericRequestBuilder或其子类。现在,来看GenericRequestBuilder.into()
3.0 GenericRequestBuilder#into()
前面首先会判断当前线程,只有主线程才能继续执行。
并且,如果没有设置过transform()或centerCrop,那么以ImageView的scaleType属性为准。
public Target<TranscodeType> into(ImageView view) {
Util.assertMainThread(); //判断是否是主线程,如果不是会抛出异常。
//...
//如果没有设置transform()或centerCrop(),那么以ImageView的scaleType属性为准
if (!isTransformationSet && view.getScaleType() != null) {
switch (view.getScaleType()) {
case CENTER_CROP:
applyCenterCrop();
break;
case FIT_CENTER:
case FIT_START:
case FIT_END:
applyFitCenter();
break;
//$CASES-OMITTED$
default:
// Do nothing.
}
}
return into(glide.buildImageViewTarget(view, transcodeClass));
}
3.1 glide.buildImageViewTarget
来看Glide.buildImageViewTarget,在这个方法中会调用ImageViewTargetFactory#buildTarget()
public <Z> Target<Z> buildTarget(ImageView view, Class<Z> clazz) {
if (GlideDrawable.class.isAssignableFrom(clazz)) {
return (Target<Z>) new GlideDrawableImageViewTarget(view);
} else if (Bitmap.class.equals(clazz)) {
return (Target<Z>) new BitmapImageViewTarget(view);
} else if (Drawable.class.isAssignableFrom(clazz)) {
return (Target<Z>) new DrawableImageViewTarget(view);
} else {
throw new IllegalArgumentException("Unhandled class: " + clazz
+ ", try .as*(Class).transcode(ResourceTranscoder)");
}
}
这是个工厂方法,根据当前传入的clazz参数返回相应的类
- 如果之前调用过asBitmap()方法,那么会返回BitmapImageViewTarget对象
- 否则一般都是返回GlideDrawableImageViewTarget对象
- 其他情况通常用不到
注意这里
BitmapImageViewTarget和DrawableImageViewTarget就是具体是设置图片到ImageView的实现类,以DrawableImageViewTarget为例,可以看到view.setImageDrawable(resource)
public class DrawableImageViewTarget extends ImageViewTarget<Drawable> {
public DrawableImageViewTarget(ImageView view) {
super(view);
}
/**
* @deprecated Use {@link #waitForLayout()} instead.
*/
// Public API.
@SuppressWarnings({"unused", "deprecation"})
@Deprecated
public DrawableImageViewTarget(ImageView view, boolean waitForLayout) {
super(view, waitForLayout);
}
@Override
protected void setResource(@Nullable Drawable resource) {
view.setImageDrawable(resource);
}
}
回到1.0.0,我们再来看into方法
3.2 GenericRequestBuilder#into(Y target)
在这个方法中,主要会构建出一个Request对象,并执行这个Request对象。
public <Y extends Target<TranscodeType>> Y into(Y target) {
Util.assertMainThread();
//...
Request previous = target.getRequest();
if (previous != null) {
previous.clear();
requestTracker.removeRequest(previous);
previous.recycle();
}
//1.2.1 构建出了一个Request对象
Request request = buildRequest(target);
target.setRequest(request);
lifecycle.addListener(target);
//1.2.3 执行这个request
requestTracker.runRequest(request);
return target;
}
3.3 buildRequest
先来看buildRequest,这里分成三种情况,但最终都会调用obtainRequest
private Request buildRequestRecursive(Target<TranscodeType> target, ThumbnailRequestCoordinator parentCoordinator) {
if (thumbnailRequestBuilder != null) {
//设置过thumbnail(GenericRequestBuilder)或thumbnail(
DrawableRequestBuilder)会调用这里
//...
Request fullRequest = obtainRequest(target, sizeMultiplier, priority, coordinator);
//...
coordinator.setRequests(fullRequest, thumbRequest);
return coordinator;
} else if (thumbSizeMultiplier != null) {
//设置过 thumbnail(float)会调用这里
//...
Request thumbnailRequest = obtainRequest(target, thumbSizeMultiplier, getThumbnailPriority(), coordinator);
coordinator.setRequests(fullRequest, thumbnailRequest);
return coordinator;
} else {
//没有设置过thumbnail(缩略图)会调用这里
//...
return obtainRequest(target, sizeMultiplier, priority, parentCoordinator);
}
}
private Request obtainRequest(Target<TranscodeType> target, float sizeMultiplier, Priority priority,
RequestCoordinator requestCoordinator) {
return GenericRequest.obtain(
loadProvider,
model,
signature,
context,
priority,
target,
sizeMultiplier,
placeholderDrawable,
placeholderId,
errorPlaceholder,
errorId,
fallbackDrawable,
fallbackResource,
requestListener,
requestCoordinator,
glide.getEngine(),
transformation,
transcodeClass,
isCacheable,
animationFactory,
overrideWidth,
overrideHeight,
diskCacheStrategy);
}
3.3.2 GenericRequestBuilder#obtainRequest
来看obtainRequest,首先如果request没有初始化,则new GenericRequest对象。接着调用GenericRequest#into方法 ,其内部是一些赋值的代码,将传入的这些参数赋值到GenericRequest的成员变量中。
public static <A, T, Z, R> GenericRequest<A, T, Z, R> obtain(...很多参数...) {
//...
if (request == null) {
//创建GenericRequest对象
request = new GenericRequest<A, T, Z, R>();
}
//内部是一些赋值的代码,将传入的这些参数赋值到GenericRequest的成员变量当中
request.init(loadProvider,
model,
signature,
context,
priority,
target,
sizeMultiplier,
placeholderDrawable,
placeholderResourceId,
errorDrawable,
errorResourceId,
fallbackDrawable,
fallbackResourceId,
requestListener,
requestCoordinator,
engine,
transformation,
transcodeClass,
isMemoryCacheable,
animationFactory,
overrideWidth,
overrideHeight,
diskCacheStrategy);
return request;
}
####3.4 ReuqestTracker#runRequest ####
回到3.2,来看runRequest,这里是真正执行的地方。可以看到如果没有处于暂停状态,会直接调用request.begein(),如果处于暂停状态,那么先添加到队列中,等恢复到正常状态时,会再调用request.begin()。即无论如何都会调用request.begin()
public void runRequest(Request request) {
requests.add(request);
if (!isPaused) {
request.begin();
} else {
pendingRequests.add(request);
}
}
3.5 request#begin()
那这个request到底是哪类类呢? 就是我们前面在 1.2.2 GenericRequestBuilder#obtainRequest中分析的GenericRequest。
在这里无论是onSizeReady还是target.getSize,最终都会调用onSizeReady。
@Override
public void begin() {
//...
if (model == null) {
//model是存储url的,这里会调用setErrorPlaceholder,从而最终调用setImageDrawable
onException(null);
return;
}
status = Status.WAITING_FOR_SIZE;
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
//使用了override() API指定了固定的宽高 调用这里
onSizeReady(overrideWidth, overrideHeight);
} else {
//没有使用了override() API指定固定的宽高 调用这里
//这个target.getSize()方法的内部会根据ImageView的layout_width和layout_height值做一系列的计算,来算出图片应该的宽高。
target.getSize(this);
}
if (!isComplete() && !isFailed() && canNotifyStatusChanged()) {
target.onLoadStarted(getPlaceholderDrawable());
}
//...
}
3.6 onSizeReady
onSizeReady会确定图片的宽高并调用engine.load来执行加载。
public void onSizeReady(int width, int height) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("Got onSizeReady in " + LogTime.getElapsedMillis(startTime));
}
if (status != Status.WAITING_FOR_SIZE) {
return;
}
status = Status.RUNNING;
width = Math.round(sizeMultiplier * width);
height = Math.round(sizeMultiplier * height);
//loadProvider内部封装了GifBitmapWrapperDrawableTranscoder、ImageVideoModelLoader、ImageVideoGifDrawableLoadProvider,
//这个对象是从load方法中构建出来的 -> 具体在DrawableTypeRequest构造方法中
//获取ImageVideoModelLoader
ModelLoader<A, T> modelLoader = loadProvider.getModelLoader();
//获取ImageVideoFetcher
final DataFetcher<T> dataFetcher = modelLoader.getResourceFetcher(model, width, height);
if (dataFetcher == null) {
onException(new Exception("Failed to load model: \'" + model + "\'"));
return;
}
//获取GifBitmapWrapperDrawableTranscoder
ResourceTranscoder<Z, R> transcoder = loadProvider.getTranscoder();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime));
}
loadedFromMemoryCache = true;
//[重点]
loadStatus = engine.load(signature, width, height, dataFetcher, loadProvider, transformation, transcoder,
priority, isMemoryCacheable, diskCacheStrategy, this);
loadedFromMemoryCache = resource != null;
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("finished onSizeReady in " + LogTime.getElapsedMillis(startTime));
}
}
3.7 engine.load
这个方法中分为两步,第一步处理缓存,第二步真正执行加载,
构建出EngineJob,并把callback (callback是GenericRequest对象)添加到EngineJob中,并且执行刚new出来的EngineRunnable
public <T, Z, R> LoadStatus load(Key signature, int width, int height, DataFetcher<T> fetcher,
DataLoadProvider<T, Z> loadProvider, Transformation<Z> transformation, ResourceTranscoder<Z, R> transcoder,
Priority priority, boolean isMemoryCacheable, DiskCacheStrategy diskCacheStrategy, ResourceCallback cb) {
//处理缓存
final String id = fetcher.getId();
EngineKey key = keyFactory.buildKey(id, signature, width, height, loadProvider.getCacheDecoder(),
loadProvider.getSourceDecoder(), transformation, loadProvider.getEncoder(),
transcoder, loadProvider.getSourceEncoder());
EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
if (cached != null) {
cb.onResourceReady(cached);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Loaded resource from cache", startTime, key);
}
return null;
}
EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
if (active != null) {
cb.onResourceReady(active);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Loaded resource from active resources", startTime, key);
}
return null;
}
EngineJob current = jobs.get(key);
if (current != null) {
current.addCallback(cb);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Added to existing load", startTime, key);
}
return new LoadStatus(cb, current);
}
EngineJob engineJob = engineJobFactory.build(key, isMemoryCacheable);
DecodeJob<T, Z, R> decodeJob = new DecodeJob<T, Z, R>(key, width, height, fetcher, loadProvider, transformation,
transcoder, diskCacheProvider, diskCacheStrategy, priority);
EngineRunnable runnable = new EngineRunnable(engineJob, decodeJob, priority);
jobs.put(key, engineJob);
engineJob.addCallback(cb);
//真正执行
engineJob.start(runnable);
//...
return new LoadStatus(cb, engineJob);
}
3.8 EngineRunnable#run()
engineJob.start()会执行EngineRunnable的run方法。
public void run() {
if (isCancelled) {
return;
}
Exception exception = null;
Resource<?> resource = null;
try {
//1.3.0 解码
resource = decode();
} catch (Exception e) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Exception decoding", e);
}
exception = e;
}
if (isCancelled) {
if (resource != null) {
resource.recycle();
}
return;
}
//1.3.2 加载结果
if (resource == null) {
onLoadFailed(exception);
} else {
onLoadComplete(resource);
}
}
3.9 decode
decode方法进行了解码,返回Resource对象,详情看 Glide源码解析04-decode
3.10 onLoadFailed or onLoadComplete
如果resource为null,则执行加载失败的逻辑,如果不为null,则执行加载成功的逻辑。详情看Glide源码解析05-onLoadComplete
###更多
Glide源码解析01-with
Glide源码解析02-load
Glide源码解析03-into
Glide源码解析04-decode
Glide源码解析05-onLoadComplete
Glide源码解析06-Glide流程图