Glide 的请求执行过程
- 要了解请求执行过程首先我们需要知道如下问题
- 何时构建的请求
- 何时执行的请求
- 如何构建的请求
- 执行请求
1.请求执行时机&2.请求构建时机
-
在源码流程分析里我们提到调用
into()
开始执行图片请求public <Y extends Target<TranscodeType>> Y into(Y target) { //省略部分代码 //1. 获取之前的请求 Request previous = target.getRequest(); //2.判断之前的请求是否为空 if (previous != null) { previous.clear(); //将其从追踪器移除方便追踪器追踪下面最新的request requestTracker.removeRequest(previous); //内部调用 REQUEST_POOL.offer(this);方法,将请求放入请求池以供复用 previous.recycle(); } // 3.根据target 生成 request Request request = buildRequest(target); // 4.内部调用了setTag方法给view这只TAG,防止列表图片错乱 target.setRequest(request); //5.给lifecycle 添加回调(target实现了LifeCycleListener接口) // 这里的lifeCycle就是RequestManagerFragment(无界面fragemnt)里的lifeCycle lifecycle.addListener(target); // 6 请求追踪器运行request requestTracker.runRequest(request); return target; }
-
根据上面的代码我们可以得到上面1,2 的答案
- 在调用
into
方法的时候先去构建请求,再去执行请求
- 在调用
3.如何构建请求
-
根据上面代码可知在调用
buildRequest(target);
的时候构建了请求private Request buildRequest(Target<TranscodeType> target) { if (priority == null) { priority = Priority.NORMAL; } return buildRequestRecursive(target, null); } // 1 可以看到调用buildRequestRecursive(target, null) private Request buildRequestRecursive(Target<TranscodeType> target, ThumbnailRequestCoordinator parentCoordinator) { //部分代码 判断是否设置缩略图以及缩略图比例 //最终都会执行obtainRequest方法 return obtainRequest方法(target, sizeMultiplier, priority, parentCoordinator); } //2 该方法最终执行到GenericRequest public static <A, T, Z, R> GenericRequest<A, T, Z, R> obtain(//参数列表){ GenericRequest<A, T, Z, R> request = (GenericRequest<A, T, Z, R>) REQUEST_POOL.poll(); if (request == null) { request = new GenericRequest<A, T, Z, R>(); } request.init(//参数列表); return request; } // 3 调用了init 方法生成request private void init( LoadProvider<A, T, Z, R> loadProvider, A model, Key signature, Context context, Priority priority, Target<R> target, float sizeMultiplier, Drawable placeholderDrawable, int placeholderResourceId, Drawable errorDrawable, int errorResourceId, Drawable fallbackDrawable, int fallbackResourceId, RequestListener<? super A, R> requestListener, RequestCoordinator requestCoordinator, Engine engine, Transformation<Z> transformation, Class<R> transcodeClass, boolean isMemoryCacheable, GlideAnimationFactory<R> animationFactory, int overrideWidth, int overrideHeight, DiskCacheStrategy diskCacheStrategy) { this.loadProvider = loadProvider; this.model = model; this.signature = signature; this.fallbackDrawable = fallbackDrawable; this.fallbackResourceId = fallbackResourceId; this.context = context.getApplicationContext(); this.priority = priority; this.target = target; this.sizeMultiplier = sizeMultiplier; this.placeholderDrawable = placeholderDrawable; this.placeholderResourceId = placeholderResourceId; this.errorDrawable = errorDrawable; this.errorResourceId = errorResourceId; this.requestListener = requestListener; this.requestCoordinator = requestCoordinator; this.engine = engine; this.transformation = transformation; this.transcodeClass = transcodeClass; this.isMemoryCacheable = isMemoryCacheable; this.animationFactory = animationFactory; this.overrideWidth = overrideWidth; this.overrideHeight = overrideHeight; this.diskCacheStrategy = diskCacheStrategy; status = Status.PENDING; } // 可以看到 init 方法里就是一些设置属性的初始化操作 就这样构建完了request
- 通过GenericRequest的init方法 设置属性 完成request的初始化
4.执行请求
-
上文我们知通过请求追踪器来执行request
requestTracker.runRequest(request);
requestTracker
是什么?
-
定义
-
用于跟踪、取消和重新启动正在进行、已完成和失败的请求的类。(请求追踪器)
-
内部维护两个集合
-
// requests正在执行的请求队列,保证不被使用的request被回收 Set<Request> requests = Collections.newSetFromMap(new WeakHashMap<Request, Boolean>()) //尚未完成的等待排队请求的队列 List<Request> pendingRequests = new ArrayList<Request>();
-
-
执行过程
- runRequest
/**
* 开始追踪请求
*/
public void runRequest(Request request) {
requests.add(request);
// 判断当前请求是否暂停 不是则执行begin
if (!isPaused) {
request.begin();
} else {
// 请求暂停则加入等待队列 根据绑定的声明周期来判断是否处于暂停状态 onstart 开始执行 onStop暂停执行
pendingRequests.add(request);
}
}
- begin 方法
public void begin() {
//1.判断是否调用了override指定宽高
status = Status.WAITING_FOR_SIZE;
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
//2.若指定宽高则直接使用该宽高加载图片 重点 onSizeReady
onSizeReady(overrideWidth, overrideHeight);
} else {
//3. 若未指定宽高则根据绘制结果测量宽高,最终还是调用onSizeReady
//这里的this 就是SizeReadyCallback的实现onSizeReady
target.getSize(this);
}
if (!isComplete() && !isFailed() && canNotifyStatusChanged()) {
// 4 读取默认图并设置给target
target.onLoadStarted(getPlaceholderDrawable());
}
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("finished run method in " + LogTime.getElapsedMillis(startTime));
}
}
-
getSize方法
-
public void getSize(SizeReadyCallback cb) { int currentWidth = getViewWidthOrParam(); int currentHeight = getViewHeightOrParam(); // 如果已经完成绘制且宽高有效则调用 onSizeReady if (isSizeValid(currentWidth) && isSizeValid(currentHeight)) { cb.onSizeReady(currentWidth, currentHeight); } else { if (!cbs.contains(cb)) { cbs.add(cb); } // 如果绘制没结束则加入观察者 if (layoutListener == null) { final ViewTreeObserver observer = view.getViewTreeObserver(); layoutListener = new SizeDeterminerLayoutListener(this); observer.addOnPreDrawListener(layoutListener); } } }
-
可以看到最终都调用onSizeReady
- 设置了override 指定宽高的的直接调用
- 未指定宽高的 则根据测量结果获取宽高后调用
-
-
onSizeReady
-
public void onSizeReady(int width, int height) { //省略部分代码 width = Math.round(sizeMultiplier * width); height = Math.round(sizeMultiplier * height); //1. 获取modelloader ModelLoader<A, T> modelLoader = loadProvider.getModelLoader(); //2。通过modelloader获取DataFetcher final DataFetcher<T> dataFetcher = modelLoader.getResourceFetcher(model, width, height); //3. 获取转码器 ResourceTranscoder<Z, R> transcoder = loadProvider.getTranscoder(); loadedFromMemoryCache = true; // 4. 调用engine.load完成真正的图片加载 loadStatus = engine.load(signature, width, height, dataFetcher, loadProvider, transformation, transcoder, priority, isMemoryCacheable, diskCacheStrategy, this); loadedFromMemoryCache = resource != null; //省略部分代码 }
- ModelLoader
- 一个工厂接口,用于将任意复杂的数据模型转换为原始数据类型 (传递String,url则对应就是io输入流inputstream),从而能够使用DataFetcher去获取由该模型表示的资源的数据。
- DataFetcher
- 一个接口,具有多个实现类都代表从指定数据源加载数据,通过ModelLoader创建
- 比如我们传递
Sting 类型url
则DataFetcher
对应的实现类为HttpUrlFetcher
从url获取资源也就是网络请求
- ResourceTranscoder
- 将一种类型的资源转码为另一种类型的资源。
- 比如BitmapDrawableTranscoder将Bitmap转码为BitmapDrawable
- engine.load
- 真正加载图片的地方
- ModelLoader
-
engine.load
-
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) { Util.assertMainThread(); long startTime = LogTime.getLogTime(); //获取id字符转 加载图片的唯一标识 final String id = fetcher.getId(); //生成缓存的key 重写equals hash 算法生成 EngineKey key = keyFactory.buildKey(id, signature, width, height, loadProvider.getCacheDecoder(), loadProvider.getSourceDecoder(), transformation, loadProvider.getEncoder(), transcoder, loadProvider.getSourceEncoder()); //根据key 获取 缓存 EngineResource<?> cached = loadFromCache(key, isMemoryCacheable); //此时得到缓存 若不为空则调用ResourceCallback.onResourceReady 将缓存回调出去 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) { // 调用onResourceReady 给target 设置图片 cb.onResourceReady(active); if (Log.isLoggable(TAG, Log.VERBOSE)) { logWithTimeAndKey("Loaded resource from active resources", startTime, key); } return null; } // 若缓存中没有则开启新线程 创建 EngineJob 来从磁盘或者网络里加载 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); } // 若内存缓存 和 弱引用缓存获取不到则开启线程创建EngineRunnable 去磁盘或者网络加载执行逻辑也就在EngineRunnable的run方法中 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); }
-
-
向下执行到
EngineRunnable
的run
方法-
public void run() { // ...... resource = decode(); // ...... if (resource == null) { onLoadFailed(exception); } else { onLoadComplete(resource); } } //decode private Resource<?> decode() throws Exception { //磁盘缓存默认为auto 根据图片大小和数量来决定是否磁盘缓存 if (isDecodingFromCache()) { // 从磁盘读取并解码 return decodeFromCache(); } else { //从网络读取并解码 return decodeFromSource(); } }
-
当获取成功后调用
onLoadComplete
失败调用onLoadFailed
-
private void onLoadComplete(Resource resource) { //这里的manager 就是EngineJob manager.onResourceReady(resource);}
-
通过调用
onResourceReady
来传递资源 -
@Overridepublic void onResourceReady(final Resource<?> resource) { this.resource = resource; MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();}
-
可以看到通过
handle
发送了一个message-
Handler MAIN_THREAD_HANDLER = new Handler(Looper.getMainLooper(), new MainThreadCallback());
-
上面是Handler 创建可以看到传递了
MainThreadCallback
-
该CallBack 就是处理返回结果的地方
-
-
private static class MainThreadCallback implements Handler.Callback { @Override public boolean handleMessage(Message message) { if (MSG_COMPLETE == message.what || MSG_EXCEPTION == message.what) { EngineJob job = (EngineJob) message.obj; if (MSG_COMPLETE == message.what) { // 处理主线程任务 job.handleResultOnMainThread(); } else { //处理主线程异常 job.handleExceptionOnMainThread(); } return true; } return false; } }
-
处理主线程任务
-
private void handleResultOnMainThread() { //.... engineResource = engineResourceFactory.build(resource, isCacheable); hasResource = true; //若有一个listener 引用则不是放,引用次数+1 放到弱引用缓存中 engineResource.acquire(); listener.onEngineJobComplete(key, engineResource); for (ResourceCallback cb : cbs) { if (!isInIgnoredCallbacks(cb)) { engineResource.acquire(); //调用回调 返回 图片resource cb.onResourceReady(engineResource); } } // 此时 我们的请求已完成,因此我们可以释放资源。若引用次数为0 则从弱引用缓存队列移除并添加到内存缓存中 engineResource.release(); }
-
onResourceReady
-
public void onResourceReady(Resource<?> resource) { onResourceReady(resource, (R) received);}private void onResourceReady(Resource<?> resource, R result) { //调用targrt的onResourceReady target.onResourceReady(result, animation);}//我们以imageviewTargt为例子 @Overridepublic void onResourceReady(Z resource, GlideAnimation<? super Z> glideAnimation) { //设置图片资源 以BitmapImageViewTarget 为例子 setResource(resource); }//BitmapImageViewTargetpublic class BitmapImageViewTarget extends ImageViewTarget<Bitmap> { public BitmapImageViewTarget(ImageView view) { super(view); } protected void setResource(Bitmap resource) { // 设置图片资源 view.setImageBitmap(resource); }}
-
至此图片加载完成
-
-
执行过程总结
- 通过
requesttracker
执行request
加入set集合,判断是否在执行 若在执行则调用begin,否则加入等待集合 - 调用begin,计算target宽高,调用onSizeReady
- 在
onSizeReady
里 获取ModelLoader,DataFetcher,ResourceTranscoder
,调用engine.load
执行真正的加载过程 - 在engine.load方法中
- 先从内存缓存获取,若不存在则从弱引用缓存获取,通过
onResourceReady
回调将资源设置给target - 若二者都不存在则创建EngineRunnable从磁盘或者网络获取,获取到之后通过handler转换到主线程,再通过
onResourceReady
回调将资源设置给target
- 先从内存缓存获取,若不存在则从弱引用缓存获取,通过
注
- 综上可知真正的图片加载执行过程是在engine.load里
- 在这个load 里面涉及到了内存缓存和磁盘缓存以及网络请求获取图片数据所以后面和缓存部分一起说
- 本文不涉及网络请求相关和缓存相关,后面请看缓存相关