target.setRequest(request)也是一个比较值得注意的地方,如果target是ViewTarget,那么request会被设置到View的tag上。这样其实是有一个好处,每一个View有一个自己的Request,如果有重复请求,那么都会先去拿到上一个已经绑定的Request,并且从RequestManager中清理回收掉。这应该是去重的功能。
4.2 requestManager.track(target, request)
这个方法非常的复杂,主要用于触发请求、编解码、装载和缓存这些功能。下面就一步一步来看吧:
4.2.1 缓存target,并启动Request
void track(Target> target, Request request) {
targetTracker.track(target);
requestTracker.runRequest(request);
}
/**
继续看一下SingleRequest中的begin方法:
@Override
public void begin() {
stateVerifier.throwIfRecycled();
startTime = LogTime.getLogTime();
// 如果model空的,那么是不能执行的。 这里的model就是前面提到的RequestBuilder中的model
if (model == null) {
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
width = overrideWidth;
height = overrideHeight;
}
// Only log at more verbose log levels if the user has set a fallback drawable, because
// fallback Drawables indicate the user expects null models occasionally.
int logLevel = getFallbackDrawable() == null ? Log.WARN : Log.DEBUG;
onLoadFailed(new GlideException(“Received null model”), logLevel);
return;
}
status = Status.WAITING_FOR_SIZE;
// 如果当前的View尺寸已经加载获取到了,那么就会进入真正的加载流程。
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
onSizeReady(overrideWidth, overrideHeight);
} else {
// 反之,当前View还没有画出来,那么是没有尺寸的。
// 这里会调用到ViewTreeObserver.addOnPreDrawListener。
// 等待View的尺寸都ok,才会继续
target.getSize(this);
}
// 如果等待和正在执行状态,那么当前会加载占位符Drawable
if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)
&& canNotifyStatusChanged()) {
target.onLoadStarted(getPlaceholderDrawable());
}
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("finished run method in " + LogTime.getElapsedMillis(startTime));
}
}
接下来是target.getSize(this)方法。这里主要说一下尺寸未加载出来的情况(ViewTarget.java):
void getSize(SizeReadyCallback cb) {
int currentWidth = getViewWidthOrParam();
int currentHeight = getViewHeightOrParam();
if (isSizeValid(currentWidth) && isSizeValid(currentHeight)) {
cb.onSizeReady(currentWidth, currentHeight);
} else {
// We want to notify callbacks in the order they were added and we only expect one or two
// callbacks to
// be added a time, so a List is a reasonable choice.
if (!cbs.contains(cb)) {
cbs.add(cb);
}
if (layoutListener == null) {
final ViewTreeObserver observer = view.getViewTreeObserver();
layoutListener = new SizeDeterminerLayoutListener(this);
// 绘画之前加入尺寸的监听。这一点我想大部分Android开发同学应该都知道。
// 接下来在看看系统触发该Listener时target又干了些什么。
observer.addOnPreDrawListener(layoutListener);
}
}
}
private static class SizeDeterminerLayoutListener implements ViewTreeObserver
.OnPreDrawListener {
// 注意这里是弱引用
private final WeakReference sizeDeterminerRef;
public SizeDeterminerLayoutListener(SizeDeterminer sizeDeterminer) {
sizeDeterminerRef = new WeakReference<>(sizeDeterminer);
}
@Override
public boolean onPreDraw() {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, “OnGlobalLayoutListener called listener=” + this);
}
SizeDeterminer sizeDeterminer = sizeDeterminerRef.get();
if (sizeDeterminer != null) {
// 通知SizeDeterminer去重新检查尺寸,并触发后续操作。
// SizeDeterminer有点像工具类,又作为尺寸回调的检测接口
sizeDeterminer.checkCurrentDimens();
}
return true;
}
}
ok,继续回到SingleRequest.onSizeReady方法,主要就是Engine发起load操作
public void onSizeReady(int width, int height) {
stateVerifier.throwIfRecycled();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("Got onSizeReady in " + LogTime.getElapsedMillis(startTime));
}
if (status