Glide.with(imageView.context).load(url).into(imageView)
这一串代码是加载图片的最简形式.
分别传递了3个参数
- context主要用于生成framgnet控制glide加载生命周期
- 基于url生成key,找到缓存中对应的图片资源
- 有了图片资源后,加载到imageView中
生命周期的控制——RequestManager
@NonNull
public static RequestManager with(@NonNull Context context) {
return getRetriever(context).get(context);
}
getRetriever中获取glide的RequestManagerRetriever
- 若glide为null,则会用单例模式构造
- RequestManagerRetriever
RequestManagerRetriever中通过对context类型的判断,生成RequestManagerFragment/SupportRequestManagerFragment.通过这个framgnet获取生命周期和RequestManagerTreeNode,生成RequestManager
- 这里的生命周期和androidX中的不是同一个,但作用类似
- 同一个context只会生成一个RequestManagerFragment/SupportRequestManagerFragment,并且只有这一个RequestManager
RequestManager(
Glide glide,
Lifecycle lifecycle,
RequestManagerTreeNode treeNode,
RequestTracker requestTracker,
ConnectivityMonitorFactory factory,
Context context) {
...
// If we're the application level request manager, we may be created on a background thread.
// In that case we cannot risk synchronously pausing or resuming requests, so we hack around the
// issue by delaying adding ourselves as a lifecycle listener by posting to the main thread.
// This should be entirely safe.
if (Util.isOnBackgroundThread()) {
mainHandler.post(addSelfToLifecycle);
} else {
lifecycle.addListener(this);
}
lifecycle.addListener(connectivityMonitor);
...
}
RequestManager本身继承LifecycleListener,在构建的时候注册监听.
- 除了注册自身的监听,还有个ConnectivityMonitor,在有网络权限时,默认实现为DefaultConnectivityMonitor.DefaultConnectivityMonitor在接受到onStart事件时,会注册一个监听网络状态的广播,onStop时注销.当无网状态切换到有网的时候,广播便会执行requestTracker.restartRequests(),开始处理请求.
RequestManager的onStart和onStop方法中,会针对requestTracker和targetTracker这两个对象操作
/**
* Lifecycle callback that registers for connectivity events (if the
* android.permission.ACCESS_NETWORK_STATE permission is present) and restarts failed or paused
* requests.
*/
@Override
public synchronized void onStart() {
resumeRequests();
targetTracker.onStart();
}
/**
* Lifecycle callback that unregisters for connectivity events (if the
* android.permission.ACCESS_NETWORK_STATE permission is present) and pauses in progress loads.
*/
@Override
public synchronized void onStop() {
pauseRequests();
targetTracker.onStop();
}
- RequestTracker 负责跟踪Request
- TargetTracker 负责跟踪Target
RequestTracker和TargetTracker都是对数组进行操作,既然是数组,通过查看对数组操作的函数,最后定位到RequestBuilder.into函数中
private <Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener,
BaseRequestOptions<?> options,
Executor callbackExecutor) {
Request request = buildRequest(target, targetListener, options, callbackExecutor);
...
requestManager.clear(target);
target.setRequest(request);
requestManager.track(target, request);
return target;
}
加载请求的构建——RequestBuilder
在into方法中,构建了target与request
-
Target继承LifecycleListener,会被TargetTracker控制;Target有很多实现,这里transcodeClass对应的是Drawable.class,生成DrawableImageViewTarget
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) { ... return into( glideContext.buildImageViewTarget(view, transcodeClass), /*targetListener=*/ null, requestOptions, Executors.mainThreadExecutor()); }
public class ImageViewTargetFactory { @NonNull @SuppressWarnings("unchecked") 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)"); } } }
-
Request的基本实现是SingleRequest,同样会被RequestTracker控制
private Request obtainRequest( Object requestLock, Target<TranscodeType> target, RequestListener<TranscodeType> targetListener, BaseRequestOptions<?> requestOptions, RequestCoordinator requestCoordinator, TransitionOptions<?, ? super TranscodeType> transitionOptions, Priority priority, int overrideWidth, int overrideHeight, Executor callbackExecutor) { return SingleRequest.obtain( context, glideContext, requestLock, model, transcodeClass, requestOptions, overrideWidth, overrideHeight, priority, target, targetListener, requestListeners, requestCoordinator, glideContext.getEngine(), transitionOptions.getTransitionFactory(), callbackExecutor); }
上面构建Target时,之所以说transcodeClass == Drawable.class.是因为transcodeClass的类型由Glide.load函数决定的.
public RequestBuilder<Drawable> load(@Nullable Object model) {
return asDrawable().load(model);
}
public RequestBuilder<Drawable> asDrawable() {
return as(Drawable.class);
}
public <ResourceType> RequestBuilder<ResourceType> as(
@NonNull Class<ResourceType> resourceClass) {
return new RequestBuilder<>(glide, this, resourceClass, context);
}
加载的逻辑
RequestManager的onStart执行时,初始status == Status.PENDING
public void begin() {
synchronized (requestLock) {
...
status = Status.WAITING_FOR_SIZE;
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
onSizeReady(overrideWidth, overrideHeight);
} else {
target.getSize(this);
}
}
}
target.getSize(target为DrawableImageViewTarget,getSize为基类ViewTarget函数)→
SizeDeterminer.getSize(获取宽高,若宽高无效,通过注册ViewTreeObserver,在onPreDraw中获取宽高,获取到有效数据后,回调SingleRequest.onSizeReady)→
SingleRequest.onSizeReady→
Engine.load(这个时候会通过Glide.load等参数构建EngineKey,通过key去activeResources/cache中取数据)
- activeResources 没有大小限制.保存活跃的图片资源.
- cache 有大小限制.保存不展示的图片资源
- 受生命周期控制,当RequestManagerFragment/SupportRequestManagerFragment销毁的时候,从activeResources中remove添加到cache中
→waitForExistingOrStartNewJob
-
从activeResources/cache中没取到数据时,则执行这个方法,如果任务已经存在,则不重复创建,只添加回调
-
若任务不存在,则构建EngineJob和DecodeJob,并在EngineJob中启动DecodeJob
public synchronized void start(DecodeJob<R> decodeJob) { this.decodeJob = decodeJob; GlideExecutor executor = decodeJob.willDecodeFromCache() ? diskCacheExecutor : getActiveSourceExecutor(); executor.execute(decodeJob); }
-
这里利用线程池执行DecodeJob(DecodeJob本身继承Runnable)
-
decodeJob.willDecodeFromCache() 会根据diskCacheStrategy来判断使用那个线程池
boolean willDecodeFromCache() { Stage firstStage = getNextStage(Stage.INITIALIZE); return firstStage == Stage.RESOURCE_CACHE || firstStage == Stage.DATA_CACHE; } private Stage getNextStage(Stage current) { switch (current) { case INITIALIZE: return diskCacheStrategy.decodeCachedResource() ? Stage.RESOURCE_CACHE : getNextStage(Stage.RESOURCE_CACHE); case RESOURCE_CACHE: return diskCacheStrategy.decodeCachedData() ? Stage.DATA_CACHE : getNextStage(Stage.DATA_CACHE); case DATA_CACHE: // Skip loading from source if the user opted to only retrieve the resource from cache. return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE; case SOURCE: case FINISHED: return Stage.FINISHED; default: throw new IllegalArgumentException("Unrecognized stage: " + current); } }
-
diskCacheStrategy对象得追溯到Glide构造的时候,有默认实现,也有set方法.共有5种类型,ALL/NONE/DATA/RESOURCE/AUTOMATIC.默认实现为AUTOMATIC.
public final class GlideBuilder { private RequestOptionsFactory defaultRequestOptionsFactory = new RequestOptionsFactory() { @NonNull @Override public RequestOptions build() { return new RequestOptions(); } }; public GlideBuilder setDefaultRequestOptions(@Nullable final RequestOptions requestOptions) { return setDefaultRequestOptions( new RequestOptionsFactory() { @NonNull @Override public RequestOptions build() { return requestOptions != null ? requestOptions : new RequestOptions(); } }); } }
-
通过上面的分析可知,当设置的DiskCacheStrategy == AUTOMATIC == RESOURCE == ALL的时候 firstStage == Stage.RESOURCE_CACHE. DiskCacheStrategy == DATA 时 firstStage == Stage.DATA_CACHE,便会启动diskCacheExecutor.
- 线程池数量为1
-
只有DiskCacheStrategy == NONE,才会启动getActiveSourceExecutor.useUnlimitedSourceGeneratorPool和useAnimationPool默认为false,则会启动sourceExecutor
- 线程池数量由CPU核心数决定,最小为4个
private GlideExecutor getActiveSourceExecutor() { return useUnlimitedSourceGeneratorPool ? sourceUnlimitedExecutor : (useAnimationPool ? animationExecutor : sourceExecutor); }
public static int calculateBestThreadCount() { if (bestThreadCount == 0) { bestThreadCount = Math.min(MAXIMUM_AUTOMATIC_THREAD_COUNT, RuntimeCompat.availableProcessors()); } return bestThreadCount; }
DecodeJob执行完成后,会回调EngineJob.onResourceReady→
EngineJob.notifyCallbacksOfResult
- CallResourceReady.run()→SingleRequest.onResourceReady→target.onResourceReady→设置资源
- Engine.onEngineJobComplete(将资源存储到activeResources中)
加载过程——DecodeJob
- ResourceCacheGenerator 从内存中获取数据
- DataCacheGenerator 从本地缓存中获取,并存储到内存中
- SourceGenerator 从网络获取图片,并存储到本地
run→
runWrapped(初始化时,runReason == INITIALIZE)→
getNextStage(根据diskCacheStrategy,更新Stage)→
getNextGenerator(根据stage,获取需要执行的generator)→
runGenerators(while循环执行generator.startNext)→
reschedule(当循环到stage =SOURCE时执行,currentGenerator = SourceGenerator 。交给线程池,重新run)→
run→
runWrapped(runReason = SWITCH_TO_SOURCE_SERVICE)→
SourceGenerator.startNext(初始逻辑,获取loadData中的fetcher,执行fetcher的加载逻辑,fetcher执行成功后)→
SourceGenerator.onDataReady→
DecodeJob.reschedule(重新调度)→
run→
runWrapped(runReason = SWITCH_TO_SOURCE_SERVICE)→
SourceGenerator.startNext(写入本地文件逻辑)→
SourceGenerator.cacheData→
DataCacheGenerator.startNext(找到对应的LoadData,加载数据,加载完成执行callback onDataReady,再接口回调至SourceGenerator.onDataFetcherReady,再接口回调至DecodeJob.onDataFetcherReady)→
reschedule(runReason = RunReason.DECODE_DATA,重新调度)→
run→
runWrapped(runReason = SWITCH_TO_SOURCE_SERVICE)→
decodeFromRetrievedData→
decodeFromData(根据currentData类型,currentDataSource数据源类型,在Registry中找到对应的decoder和transcoder,并组建出decodePaths;根据decodePaths组建LoadPath;根据LoadPath获取Resource<>,正常为LazyBitmapDrawableResource类型)→
notifyEncodeAndRelease→
notifyComplete→触发EngineJob.onResourceReady
总结
- Glide在加载时,会生成全局唯一的glide和engine.
- 每个activity加载图片时,都会额外创建一个不可见的fragmnt,用于控制生命周期,基于此生成requestManager.
- 每个加载请求都会生成target与request,target中收集了view信息及view资源类型.在target确认好view的宽高后,会通过request触发engine的加载逻辑.
- engine会尝试从activeResources和cache中加载数据,未成功,便会创建engineJob和decodeJob.
- engineJob会启动decodeJob,尝试从ResourceCacheGenerator/DataCacheGenerator/SourceGenerator中获取数据.
- 取得数据后,便交由target设置资源,同时保存到engine的activeResources中.
- 当activity销毁时,触发生命周期销毁逻辑,资源从activeResources中remove添加到cache中.
调试日志
adb shell setprop log.tag.Engine VERBOSE 根据打印内容判断加载源
- Started new load 磁盘或者网络
- Loaded resource from active resources
- Loaded resource from cache
DecodeJob|Engine|OkHttpLoadImg|PrintingEventListener|SourceGenerator|loadImg
关闭日志 adb shell setprop log.tag.Engine ERROR
网友评论