文章目录
本文将分析图片处理框架Glide的加载流程,同时也会对缓存,网络请求,自定义模块做相应分析,文中代码使用的是目前(2020.3)最新的版本4.11.0。
Glide框架总览
Glide是一个非常复杂的框架,下面我们根据各模块的作用做出如下划分:
图片加载源码分析
Glide最基本的使用流程就是下面这行代码,其它所有扩展的额外功能都是以其建造者链式调用的基础上增加的。
GlideApp.with(context).load(url).into(imageView);
下面我们将对该用法进行深入的源码分析。
Glide.with()
Glide为我们提供多个Glide.with()
实现,我们主要围绕with(Context context)
展开分析
1. Glide.with(Context)
return getRetriever(activity).get(activity)
@Glide.java
RequestManagerRetriever getRetriever(context) {
...
return Glide.get(context).getRequestManagerRetriever();
}
//使用双检锁方式实现单例
public static Glide get(@NonNull Context context) {
if (glide == null) {
//获取用户自定义GlideModule
GeneratedAppGlideModule annotationGeneratedModule =getAnnotationGeneratedGlideModules(context.getApplicationContext());
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context, annotationGeneratedModule);
}
}
}
return glide;
}
void checkAndInitializeGlide(context, generatedAppGlideModule) {
...
initializeGlide(context, new GlideBuilder(), generatedAppGlideModule);
...
}
void initializeGlide(context, builder, annotationGeneratedModule) {
...
//1.1 获取manifest中GlideModule模块
if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
manifestModules = new ManifestParser(applicationContext).parse();
}
...
//将自定义GlideModule信息(factory)添加到GlideBuilder中
RequestManagerRetriever.RequestManagerFactory factory =
annotationGeneratedModule != null
? annotationGeneratedModule.getRequestManagerFactory : null;
builder.setRequestManagerFactory(factory);
//1.2将GlideBuilder通过applyOptions添加到GlideModule中
for (com.bumptech.glide.module.GlideModule module : manifestModules) {
module.applyOptions(applicationContext, builder);
}
if (annotationGeneratedModule != null) {
annotationGeneratedModule.applyOptions(applicationContext, builder);
}
//--> 2.创建Glide实例
Glide glide = builder.build(applicationContext);
...
//1.3 registerComponents:用于注册编解码器,ModelLoader等,具体可以参考@Resistry中的方法
if (annotationGeneratedModule != null) {
annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);
}
applicationContext.registerComponentCallbacks(glide);
Glide.glide = glide;
}
这里使用双检锁模式来获取Glide对象的单例,在1.1中,如果没有带注解的GlideModule,或者该GlideModule中isManifestParsingEnabled()为true,则调用ManifestParser解析AndroidManifest.xml中以获取值为“GlideModule”的meta-data配置,并将相应的自定义模块实例化。由于可以实例化多个GlideModule,因此得到的是一个GlideModule的List集合。
在1.2中,将builder通过applyOptions方法加入到module中,在自定义module中我们通过重写applyOptions方法可以对module进行定制。
在1.3中,提供registerComponents来修改glide中组件,用于注册编解码器,ModelLoader等,比如替换网络请求成OkHttp的方法, 就是通过该函数注册
2. GlideBuilder.build
GlideBuilder
是用来创建 Glide 实例的类,具体实现如下:
@NonNull
Glide build(@NonNull Context context) {
if (sourceExecutor == null) { //创建图片线程池
sourceExecutor = GlideExecutor.newSourceExecutor();
}
if (diskCacheExecutor == null) { //创建硬盘缓存线程池
diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
}
if (animationExecutor == null) { //创建动画线程池
animationExecutor = GlideExecutor.newAnimationExecutor();
}
//TODO:默认4M,如果是低内存设备为2M,后文[缓存机制]会有详细分析
if (memorySizeCalculator == null) {
memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
}
if (connectivityMonitorFactory == null) {
connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();
}
if (bitmapPool == null) {
int size = memorySizeCalculator.getBitmapPoolSize();
if (size > 0) {
bitmapPool = new LruBitmapPool(size);
} else {
bitmapPool = new BitmapPoolAdapter();
}
}
if (arrayPool == null) {
arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes());
}
if (memoryCache == null) { // 创建内存缓存
memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
}
if (diskCacheFactory == null) {
diskCacheFactory = new InternalCacheDiskCacheFactory(context);
}
// 创建任务和资源管理引擎(线程池,内存缓存和硬盘缓存对象)
if (engine == null) {
engine =
new Engine(
memoryCache,
diskCacheFactory,
diskCacheExecutor,
sourceExecutor,
GlideExecutor.newUnlimitedSourceExecutor(),
animationExecutor,
isActiveResourceRetentionAllowed);
}
if (defaultRequestListeners == null) {
defaultRequestListeners = Collections.emptyList();
} else {
defaultRequestListeners = Collections.unmodifiableList(defaultRequestListeners);
}
//创建requestManagerRetriever,用于创建requestManager
RequestManagerRetriever requestManagerRetriever =
new RequestManagerRetriever(requestManagerFactory);
return new Glide(
context,
engine,
memoryCache,
bitmapPool,
arrayPool,
requestManagerRetriever,
connectivityMonitorFactory,
logLevel,
defaultRequestOptionsFactory,
defaultTransitionOptions,
defaultRequestListeners,
isLoggingRequestOriginsEnabled,
isImageDecoderEnabledForBitmaps);
}
这个方法中会创建BitmapPool、MemoryCache、DiskCache等对象的实例,并在最后一句创建一个Glide对象的实例,然后将前面创建的这些实例传入到Glide对象当中,以供后续的图片加载操作使用。
同时,我们注意到,build
中创建任何对象都有一个判空的检查,只有对象为空才会去创建其实例,也就是说,我们可以applyOptions方法对这些配置对象提前初始化,进而实现更改Glide配置的功能。
具体如何自定义模块,可以参考郭神的文章:《Android图片加载框架最全解析(六),探究Glide的自定义模块功能》,文中涉及如何替换网络组件,如何替换缓存模块等非常棒的操作。
3. Glide构造方法
将任务管理对象(registry
)、array缓存、管理引擎等传入glideContext
中
Glide(...) {
...
//登记任务管理对象,根据任务类型,分发给相应任务进行处理
registry = new Registry();
...
//注册编解码器,ModelLoader等组件
registry
.append(ByteBuffer.class, new ByteBufferEncoder())
.append(InputStream.class, new StreamEncoder(arrayPool))
...
//Target工厂: 根据子类生产对应类型taget,
//包括BitmapImageViewTarget和DrawableImageViewTarget
ImageViewTargetFactory imageViewTargetFactory = new ImageViewTargetFactory();
glideContext =
new GlideContext(
context,
arrayPool,
registry,
imageViewTargetFactory,
defaultRequestOptionsFactory,
defaultTransitionOptions,
defaultRequestListeners,
engine,
isLoggingRequestOriginsEnabled,
logLevel);
}
4. RequestManagerRetriever.get
public RequestManager get(@NonNull Context context) {
if (context == null) {
throw new IllegalArgumentException("You cannot start a load on a null Context");
} else if (Util.isOnMainThread() && !(context instanceof Application)) {
//如果非ApplicationContext, 将请求的生命周期同对于的Fragment/Activity绑定
if (context instanceof FragmentActivity) {
return get((FragmentActivity) context);
} else if (context instanceof Activity) {
return get((Activity) context);
} else if (context instanceof ContextWrapper
&& ((ContextWrapper) context).getBaseContext().getApplicationContext() != null) {
return get(((ContextWrapper) context).getBaseContext());
}
}
//如果是ApplicationContext或者子线程,和Application生命周期绑定
return getApplicationManager(context);
}
@NonNull
private RequestManager supportFragmentGet(...) {
//创建一个不可见的Fragment,用于检测Activity生命周期
SupportRequestManagerFragment current =
getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) { //确保一个Activity对于一个requestManager
Glide glide = Glide.get(context);
//创建requestManger,将Glide和Activity生命周期绑定
//参考[5.requestManager生命周期]
requestManager =
factory.build(
glide, current.getGlideLifecycle(),
current.getRequestManagerTreeNode(), context);
current.setRequestManager(requestManager);
}
return requestManager;
}
通过RequestManagerRetriever.get
创建RequestManager
,详细逻辑如下:
- 如果 with 方法的
参数
为 Activity 或者Fragment
,则最终调用RequestManagerRetriever
中的fragmentGet(Context, android.app.FragmentManager)
方法创建RequestManager
; - 如果
with
方法的参数为android.support.v4.app.Fragment
或者android.support.v4.app.FragmentActivity
,则最终调用supportFragmentGet(Context, android.support.v4.app.FragmentManager)
方法创建RequestManager
; - 如果
with
方法的参数为Context
,则会判断其来源是否属于FragmentActivity
及Activity
,则按照上面的逻辑进行处理,否则最终调用getApplicationManager(Context)
方法创建RequestManager
; - 如果在子线程或者系统版本小于17,则调用
getApplicationManager(Context)
方法创建RequestManager
。
同时,由supportFragmentGet
可知,一个Activity对应一个RequestManager。
5. RequestManager生命周期
通过RequestManagerRetriever.get
创建requestManager
,通过requestManager
将Activity
和Glide
生命周期绑定。
//RequestManager构造函数
RequestManager(...) {
//在主线程绑定Glide和Activity的生命周期
if (Util.isOnBackgroundThread()) {
mainHandler.post(addSelfToLifecycle);
} else {
lifecycle.addListener(this);
}
lifecycle.addListener(connectivityMonitor);
defaultRequestListeners =
new CopyOnWriteArrayList<>(glide.getGlideContext().getDefaultRequestListeners());
setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());
glide.registerRequestManager(this);
}
private final Runnable addSelfToLifecycle =
new Runnable() {
@Override
public void run() {
//切换到主线程
lifecycle.addListener(RequestManager.this);
}
};
//RequestManager中LifecycleLister实现
public class RequestManager
implements ComponentCallbacks2, LifecycleListener, ModelTypes<RequestBuilder<Drawable>> {
...
//开始暂停的请求
public void onStart() {
resumeRequests();
}
//停止所有的请求
@Override
public void onStop() {
pauseRequests();
}
//关闭所以的请求
@Override
public void onDestroy() {
requestTracker.clearRequests();
}
...
}
通过上面 RequestManagerRetriever
和 ResquestManager
的介绍,我们知道创建 RequestManager
时需要一个 FragmentManager
参数(全局 RequestManager
除外),那么再创建 RequestManager
时会先创建一个不可见的 RequestManagerFragment ,通过 FragmentMamager加入到当前页面,用这个不可见的 Fragment 即可检测页面的生命周期,进而将Glide
和页面生命周期绑定。
6. Registry
Registry(com.bumptech.glide.Registry)是用来注册管理任务执行对象的管理类,可以简单理解为:Registry是一个工厂,而其中所有注册的对象都是一个工厂员工,当任务分发时,根据当前任务的性质,分发给相应员工进行处理。该类可细分为:ModelLoaderRegistry
、EncoderRegistry
、ResourceDecoderRegistry
、ResourceEncoderRegistry
、DataRewinderRegistry
、TranscoderRegistry
和ImageHeaderParserRegistry
共七种。Registry通过各个细分的管理类通过HashMap或者List来管理执行类及其执行方法的对应关系。
public class Registry {
@NonNull
@SuppressWarnings("unchecked")
public <X> Encoder<X> getSourceEncoder(@NonNull X data) throws NoSourceEncoderAvailableException {
//根据data通过encoderRegistry来获取对于的encoder
Encoder<X> encoder = encoderRegistry.getEncoder((Class<X>) data.getClass());
if (encoder != null) {
return encoder;
}
throw new NoSourceEncoderAvailableException(data.getClass());
}
@NonNull
public <Data> Registry append(@NonNull Class<Data> dataClass, @NonNull Encoder<Data> encoder) {
//保存dataClass和encoder对应关系到encoderRegistry工厂
encoderRegistry.append(dataClass, encoder);
return this;
}
}
public class EncoderRegistry {
private final List<Entry<?>> encoders = new ArrayList<>();
@Nullable
public synchronized <T> Encoder<T> getEncoder(@NonNull Class<T> dataClass) {
for (Entry<?> entry : encoders) {
if (entry.handles(dataClass)) {
return (Encoder<T>) entry.encoder;
}
}
return null;
}
}
7. Glide.with小结
根据上面分析,汇总成下面流程图:
从图上可以看到,Glide.with主要完成:
- 各类初始化,主要包括:线程池、缓存、
Engine
、requestManager
、register
和glideContext
; - 创建透明Fragment, 将Glide和视图生命周期进行绑定。
load(url)
1.RequestManager.load
public RequestBuilder<Drawable> load(@Nullable Bitmap bitmap) {
return asDrawable().load(bitmap);
}
2.asDrawable()
@RequestManager.java
public RequestBuilder<Drawable> asDrawable() {
return as(Drawable.class);
}
//最终返回了一个RequestBuilder
public <ResourceType> RequestBuilder<ResourceType> as(
@NonNull Class<ResourceType> resourceClass) {
return new RequestBuilder<>(glide, this, resourceClass, context);
}
protected RequestBuilder(...) {
this.glide = glide;
this.requestManager = requestManager;
this.transcodeClass = transcodeClass;
this.context = context;
this.transitionOptions = requestManager.getDefaultTransitionOptions(transcodeClass);
this.glideContext = glide.getGlideContext();
//初始化请求回调
initRequestListeners(requestManager.getDefaultRequestListeners());
apply(requestManager.getDefaultRequestOptions());
}
3.load(string)
@RequestBuilder.java
public RequestBuilder<TranscodeType> load(@Nullable String string) {
return loadGeneric(string);
}
//将url赋值给RequestBuilder.model
private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
this.model = model;
isModelSet = true;
return this;
}
可以看到,load主要是创建RequestBuilder并设置请求的URL(model),并记录了URL已设置的状态。
到此,我们可以总结出 RequestManager 两个主要作用:
- 创建 RequestBuilder,用于保存请求URL和初始化请求回调;
- 通过绑定页面生命周期来管理请求的启动结束等
into(target)
1.RequestBuilder.into
@NonNull
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
Util.assertMainThread();
Preconditions.checkNotNull(view);
BaseRequestOptions<?> requestOptions = this;
//ImageView默认ScaleType为FIT_CENTER,Glide可以通过dontTransform()或者transform(...)来关闭或使用图片变化
if (!this.isTransformationSet() && this.isTransformationAllowed() && view.getScaleType() != null) {
switch(view.getScaleType()) {
case CENTER_CROP:
requestOptions = this.clone().optionalCenterCrop();
break;
case CENTER_INSIDE:
requestOptions = this.clone().optionalCenterInside();
break;
case FIT_CENTER:
case FIT_START:
case FIT_END:
requestOptions = this.clone().optionalFitCenter();
break;
case FIT_XY:
requestOptions = this.clone().optionalCenterInside();
case CENTER:
case MATRIX:
}
}
//根据transcodeClass生成对应的ViewTarget,并指定RequestBuilder.into回调主线程执行
return (ViewTarget)this.into(this.glideContext.buildImageViewTarget(view, this.transcodeClass), (RequestListener)null, (BaseRequestOptions)requestOptions, Executors.mainThreadExecutor());
}
2.GlideContext.buildImageViewTarget
return this.imageViewTargetFactory.buildTarget(imageView, transcodeClass);
3. ImageViewTargetFactory.buidTarget
@NonNull
public <Z> ViewTarget<ImageView, Z> buildTarget(@NonNull ImageView view, @NonNull Class<Z> clazz) {
if (Bitmap.class.equals(clazz)) {
return new BitmapImageViewTarget(view);
} else if (Drawable.class.isAssignableFrom(clazz)) {
return new DrawableImageViewTarget(view);
} else {
throw new IllegalArgumentException("Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
}
}
根据这段代码可知,glideContext.buildImageViewTarget
通过传入class
类型不同,分别生成不同的ImageVieTarget
,传入Bitmap
则生成BitmapImageViewTarget
, 传入Drawable
则生成DrawableImageViewTarget
。
4. RequestBuilder.into
private <Y extends Target<TranscodeType>> Y into(@NonNull Y target, @Nullable RequestListener<TranscodeType> targetListener, BaseRequestOptions<?> options, Executor callbackExecutor) {
Preconditions.checkNotNull(target);
if (!this.isModelSet) {
throw new IllegalArgumentException("You must call #load() before calling #into()");
} else {
// -->1. 建立请求
Request request = this.buildRequest(target, targetListener, options, callbackExecutor);
Request previous = target.getRequest();
if (request.isEquivalentTo(previous) && !this.isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
if (!((Request)Preconditions.checkNotNull(previous)).isRunning()) {
previous.begin();
}
return target;
} else {
this.requestManager.clear(target);
target.setRequest(request);
// -->2. 请求追踪
this.requestManager.track(target, request);
return target;
}
}
}
RequestBuilder.into
的实现主要是buildRequest
建立请求和requestManager.track
请求追踪,下面我们将重点分析这两部分。
buildRequest
// 1. 建立请求
private Request buildRequest(Target<TranscodeType> target, @Nullable RequestListener<TranscodeType> targetListener, BaseRequestOptions<?> requestOptions, Executor callbackExecutor) {
// -->1.1 通过递归调用创建请求
return this.buildRequestRecursive(new Object(), target, targetListener, (RequestCoordinator)null, this.transitionOptions, requestOptions.getPriority(), requestOptions.getOverrideWidth(), requestOptions.getOverrideHeight(), requestOptions, callbackExecutor);
}
// 1.1 通过递归调用创建请求
private Request buildRequestRecursive(Object requestLock, Target<TranscodeType> target, @Nullable RequestListener<TranscodeType> targetListener, @Nullable RequestCoordinator parentCoordinator, TransitionOptions<?, ? super TranscodeType> transitionOptions, Priority priority, int overrideWidth, int overrideHeight, BaseRequestOptions<?> requestOptions, Executor callbackExecutor) {
// 判断当前request是否需要带error
ErrorRequestCoordinator errorRequestCoordinator = null;
if (this.errorBuilder != null) {
//errorBuilder不为空,此处为[标记1]递归调用
errorRequestCoordinator = new ErrorRequestCoordinator(requestLock, (RequestCoordinator)parentCoordinator);
parentCoordinator = errorRequestCoordinator;
}
// --> 1.2 创建带缩略图的请求
Request mainRequest = this.buildThumbnailRequestRecursive(requestLock, target, targetListener, (RequestCoordinator)parentCoordinator, transitionOptions, priority, overrideWidth, overrideHeight, requestOptions, callbackExecutor);
if (errorRequestCoordinator == null) {
//不带error直接返回mainRequest
return mainRequest;
} else {
int errorOverrideWidth = this.errorBuilder.getOverrideWidth();
int errorOverrideHeight = this.errorBuilder.getOverrideHeight();
if (Util.isValidDimensions(overrideWidth, overrideHeight) && !this.errorBuilder.isValidOverride()) {
errorOverrideWidth = requestOptions.getOverrideWidth();
errorOverrideHeight = requestOptions.getOverrideHeight();
}
// [标记1] 回调当前方法,构建带error的请求
Request errorRequest = this.errorBuilder.buildRequestRecursive(requestLock, target, targetListener, errorRequestCoordinator, this.errorBuilder.transitionOptions, this.errorBuilder.getPriority(), errorOverrideWidth, errorOverrideHeight, this.errorBuilder, callbackExecutor);
errorRequestCoordinator.setRequests(mainRequest, errorRequest);
return errorRequestCoordinator;
}
}
// 1.2 创建带缩略图的请求
private Request buildThumbnailRequestRecursive(Object requestLock, Target<TranscodeType> target, RequestListener<TranscodeType> targetListener, @Nullable RequestCoordinator parentCoordinator, TransitionOptions<?, ? super TranscodeType> transitionOptions, Priority priority, int overrideWidth, int overrideHeight, BaseRequestOptions<?> requestOptions, Executor callbackExecutor) {
if (this.thumbnailBuilder != null) { //thumbnailBuilder不不为空
if (this.isThumbnailBuilt) {
throw new IllegalStateException("You cannot use a request as both the main request and a thumbnail, consider using clone() on the request(s) passed to thumbnail()");
} else {
// 获取缩略图配置
TransitionOptions<?, ? super TranscodeType> thumbTransitionOptions = this.thumbnailBuilder.transitionOptions;
if (this.thumbnailBuilder.isDefaultTransitionOptionsSet) {
thumbTransitionOptions = transitionOptions;
}
Priority thumbPriority = this.thumbnailBuilder.isPrioritySet() ? this.thumbnailBuilder.getPriority() : this.getThumbnailPriority(priority);
int thumbOverrideWidth = this.thumbnailBuilder.getOverrideWidth();
int thumbOverrideHeight = this.thumbnailBuilder.getOverrideHeight();
if (Util.isValidDimensions(overrideWidth, overrideHeight) && !this.thumbnailBuilder.isValidOverride()) {
thumbOverrideWidth = requestOptions.getOverrideWidth();
thumbOverrideHeight = requestOptions.getOverrideHeight();
}
// 创建ThumbnailRequestCoordinator对象
ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(requestLock, parentCoordinator);
// 创建原图片请求对象
Request fullRequest = this.obtainRequest(requestLock, target, targetListener, requestOptions, coordinator, transitionOptions, priority, overrideWidth, overrideHeight, callbackExecutor);
this.isThumbnailBuilt = true;
// 用递归方式创建缩略图请求
Request thumbRequest = this.thumbnailBuilder.buildRequestRecursive(requestLock, target, targetListener, coordinator, thumbTransitionOptions, thumbPriority, thumbOverrideWidth, thumbOverrideHeight, this.thumbnailBuilder, callbackExecutor);
this.isThumbnailBuilt = false;
// 将原图片请求和缩略图请求打包到ThumbnailRequestCoordinator中
coordinator.setRequests(fullRequest, thumbRequest);
return coordinator;
}
} else if (this.thumbSizeMultiplier != null) { /缩略图缩放比例不为空
ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(requestLock, parentCoordinator);
Request fullRequest = this.obtainRequest(requestLock, target, targetListener, requestOptions, coordinator, transitionOptions, priority, overrideWidth, overrideHeight, callbackExecutor);
BaseRequestOptions<?> thumbnailOptions = requestOptions.clone().sizeMultiplier(this.thumbSizeMultiplier);
Request thumbnailRequest = this.obtainRequest(requestLock, target, targetListener, thumbnailOptions, coordinator, transitionOptions, this.getThumbnailPriority(priority), overrideWidth, overrideHeight, callbackExecutor);
coordinator.setRequests(fullRequest, thumbnailRequest);
return coordinator;
} else { //没有缩略图,直接返回原图片请求,通过obtainRequest最终返回一个SingleRequest对象
return this.obtainRequest(requestLock, target, targetListener, requestOptions, parentCoordinator, transitionOptions, priority, overrideWidth, overrideHeight, callbackExecutor);
}
}
代码中fullRequest
表示原始的请求,thumbRequest
表示缩略图请求,mainRequest表示打包了fullRequest和thumbRequest
得请求,errorRequest
错误重试请求;具体流程参考下面流程图,可以方便理解:
上面我们提到,最终得到得是一个SingleRequest
得对象,SingleRequest
以来关系如下:
public final class SingleRequest<R> implements Request, SizeReadyCallback, ResourceCallback
public interface Request {
void begin();
.......
}
public interface SizeReadyCallback {
void onSizeReady(int var1, int var2);
}
public interface ResourceCallback {
void onResourceReady(Resource<?> var1, DataSource var2);
......
}
onSizeReady()和begin()是SingleRequest
最重要得两个实现方法,相关方法得调用在requestTracker种,下面我们将分析RequstBuilder得第二个重点requestManager.track
。
5.requestManager.track
// 2.追踪Request
synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
// -->2.1 将target保存到targetTracker中
this.targetTracker.track(target);
// -->2.2 运行请求
this.requestTracker.runRequest(request);
}
// 2.1 @TargetTracker.java
private final Set<Target<?>> targets = Collections.newSetFromMap(new WeakHashMap());
public void track(@NonNull Target<?> target) {
将tartget加入set中
this.targets.add(target);
}
// 2.2 @RequestTracker.java
private final Set<Request> requests = Collections.newSetFromMap(new WeakHashMap());
private final List<Request> pendingRequests = new ArrayList();
public void runRequest(@NonNull Request request) {
this.requests.add(request);
if (!this.isPaused) {
// -->2.3调用SingleRequest.begin()方法开始请求
request.begin();
} else {
request.clear();
if (Log.isLoggable("RequestTracker", 2)) {
Log.v("RequestTracker", "Paused, delaying request");
}
//如果是暂停状态,将请求加入pending队列中
this.pendingRequests.add(request);
}
}
// 2.3 开始请求 @SingleRequest.java
public void begin() {
synchronized(this.requestLock) {
......
if (Util.isValidDimensions(this.overrideWidth, this.overrideHeight)) {
// -->2.4 请求开始
this.onSizeReady(this.overrideWidth, this.overrideHeight);
} else {
// -->2.5 如果没有override()方法设置固定宽高,根据imageView宽高计算图片宽高
this.target.getSize(this);
}
......
}
}
// 2.4 @SingleRequest
public void onSizeReady(int width, int height) {
......
// -->2.6 通过引擎加载, 倒数第二个参数,传入回调,会砸4.7中用到
this.loadStatus = this.engine.load(this.glideContext, this.model, this.requestOptions.getSignature(), this.width, this.height, this.requestOptions.getResourceClass(), this.transcodeClass, this.priority, this.requestOptions.getDiskCacheStrategy(), this.requestOptions.getTransformations(), this.requestOptions.isTransformationRequired(), this.requestOptions.isScaleOnlyOrNoTransform(), this.requestOptions.getOptions(), this.requestOptions.isMemoryCacheable(), this.requestOptions.getUseUnlimitedSourceGeneratorsPool(), this.requestOptions.getUseAnimationPool(), this.requestOptions.getOnlyRetrieveFromCache(), this, this.callbackExecutor);
......
}
// 2.5 计算图片宽高 @ViewTarget.java
void getSize(@NonNull SizeReadyCallback cb) {
......
//计算完图片宽高,最终回调2.4SingleRequest.onSizeReady方法
cb.onSizeReady(currentWidth, currentHeight);
......
}
// 2.6 通过引擎加载 @Engine.java
public <R> Engine.LoadStatus load(...) {
synchronized(this) {
// -->2.7 加载缓存
memoryResource = this.loadFromMemory(key, isMemoryCacheable, startTime);
if (memoryResource == null) {
// -->2.8 没缓存,加载网络资源
return this.waitForExistingOrStartNewJob(...);
}
}
// 回到到singleRequest类中
cb.onResourceReady(memoryResource, DataSource.MEMORY_CACHE);
return null;
}
// 2.7 加载缓存 @Engine.java
@Nullable
private EngineResource<?> loadFromMemory(EngineKey key, boolean isMemoryCacheable, long startTime) {
if (!isMemoryCacheable) {
// 如果设置为不使用缓存,直接返回
return null;
} else {
// 首先,在弱引用缓存map中查找,找到就直接返回active
EngineResource<?> active = this.loadFromActiveResources(key);
if (active != null) {
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Loaded resource from active resources", startTime, key);
}
return active;
} else {
// 接着在内存memoryCache中寻找,找到就直接返回cache
// memoryCache在GlideBuilder.build中初始化,为LruResourceCache上文有相关代码
EngineResource<?> cached = this.loadFromCache(key);
if (cached != null) {
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Loaded resource from cache", startTime, key);
}
return cached;
} else {
return null;
}
}
}
}
//2.8 没缓存,加载网络资源 @Engine.java
private <R> Engine.LoadStatus waitForExistingOrStartNewJob(...) {
EngineJob<?> current = this.jobs.get(key, onlyRetrieveFromCache);
if (current != null) {
current.addCallback(cb, callbackExecutor);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Added to existing load", startTime, key);
}
return new Engine.LoadStatus(cb, current);
} else {
// 创建下载工程任务类
EngineJob<R> engineJob = this.engineJobFactory.build(key, isMemoryCacheable, useUnlimitedSourceExecutorPool, useAnimationPool, onlyRetrieveFromCache);
// 创建解析工作对象
DecodeJob<R> decodeJob = this.decodeJobFactory.build(glideContext, model, key, signature, width, height, resourceClass, transcodeClass, priority, diskCacheStrategy, transformations, isTransformationRequired, isScaleOnlyOrNoTransform, onlyRetrieveFromCache, options, engineJob);
// 存入Jobs内部维护的HashMap中
this.jobs.put(key, engineJob);
engineJob.addCallback(cb, callbackExecutor);
// -->2.9 启动请求线程
engineJob.start(decodeJob);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Started new load", startTime, key);
}
return new Engine.LoadStatus(cb, engineJob);
}
}
// 2.9 启动请求线程, 根据配置不同,使用不同的解码线程池 @Engine.java
public synchronized void start(DecodeJob<R> decodeJob) {
this.decodeJob = decodeJob;
GlideExecutor executor = decodeJob.willDecodeFromCache() ? this.diskCacheExecutor : this.getActiveSourceExecutor();
// -->2.10 启动解码任务
executor.execute(decodeJob);
}
// 2.10 启动解码任务 @DecodeJob.java
public void run() {
......
try {
if (!this.isCancelled) {
// -->2.11 运行解码任务
this.runWrapped();
return;
}
......
}
//2.11 运行解码任务 @DecodeJob.java
private void runWrapped() {
switch(this.runReason) {
case INITIALIZE:
// -->2.12 根据缓存策略生成对应stage,stage的推进就代表缓存的查找顺序
this.stage = this.getNextStage(DecodeJob.Stage.INITIALIZE);
// -->2.13 根据stage生成Generator
this.currentGenerator = this.getNextGenerator();
// -->2.14 执行Generator的startNext()方法
this.runGenerators();
break;
case SWITCH_TO_SOURCE_SERVICE:
this.runGenerators();
break;
case DECODE_DATA:
this.decodeFromRetrievedData();
break;
default:
throw new IllegalStateException("Unrecognized run reason: " + this.runReason);
}
}
//2.12 根据缓存策略生成对应stage @DecodeJob.java
private DecodeJob.Stage getNextStage(DecodeJob.Stage current) {
switch(current) {
case RESOURCE_CACHE: //如果支持原图尺寸,下一个state就是DATA_CACHE,否则,从DATA_CACHE开始往下判断
return this.diskCacheStrategy.decodeCachedData() ? DecodeJob.Stage.DATA_CACHE : this.getNextStage(DecodeJob.Stage.DATA_CACHE);
case DATA_CACHE: //如果只读缓存,下一个Stage为FINISHED,否则就是SOURCE
return this.onlyRetrieveFromCache ? DecodeJob.Stage.FINISHED : DecodeJob.Stage.SOURCE;
case SOURCE:
case FINISHED:
return DecodeJob.Stage.FINISHED;
case INITIALIZE: //如果支持多尺寸,下一个state就是RESOURCE_CACHE,否则,从RESOURCE_CACHE开始往下判断
return this.diskCacheStrategy.decodeCachedResource() ? DecodeJob.Stage.RESOURCE_CACHE : this.getNextStage(DecodeJob.Stage.RESOURCE_CACHE);
default:
throw new IllegalArgumentException("Unrecognized stage: " + current);
}
}
// 2.13 根据stage获取Generator @DecodeJob.java
private DataFetcherGenerator getNextGenerator() {
switch(this.stage) {
case RESOURCE_CACHE: //缓存多尺寸
return new ResourceCacheGenerator(this.decodeHelper, this);
case DATA_CACHE: //缓存原图
return new DataCacheGenerator(this.decodeHelper, this);
case SOURCE: //下载远程图片
return new SourceGenerator(this.decodeHelper, this);
case FINISHED:
return null;
default:
throw new IllegalStateException("Unrecognized stage: " + this.stage);
}
}
//2.14 循环执行Generators的startNext()方法 @DecodeJob.java
private void runGenerators() {
......
while(!this.isCancelled && this.currentGenerator != null && !(isStarted = this.currentGenerator.startNext())) { //--> 2.15 执行Generator的startNext()方法
//获取下一个stage
this.stage = this.getNextStage(this.stage);
//获取下一个Generator
this.currentGenerator = this.getNextGenerator();
if (this.stage == DecodeJob.Stage.SOURCE) {
this.reschedule();
return;
}
}
......
}
// 2.15 以SourceGenerator为例,@SourceGenerator
public boolean startNext() {
......
boolean started = false;
while(!started && this.hasNextModelLoader()) {
this.loadData = (LoadData)this.helper.getLoadData().get(this.loadDataListIndex++);
// 根据缓存策略来筛选loaddata,这里最终获取的loaddata是HttpGlideUrlLoader,Fetcher是HttpUrlFetcher
if (this.loadData != null && (this.helper.getDiskCacheStrategy().isDataCacheable(this.loadData.fetcher.getDataSource()) || this.helper.hasLoadPath(this.loadData.fetcher.getDataClass()))) {
started = true;
// -->2.16 加载数据
this.startNextLoad(this.loadData);
}
}
return started;
}
// 2.16 加载数据 @SourceGenerator.java
private void startNextLoad(final LoadData<?> toStart) {
// -->2.17通过loadData方法获取图片数据
this.loadData.fetcher.loadData(this.helper.getPriority(), new DataCallback<Object>() {this.helper.getPriority(), new DataCallback<Object>() {
public void onDataReady(@Nullable Object data) {
if (SourceGenerator.this.isCurrentRequest(toStart)) {
// -->3.1 获取数据之后回调数据到SourceGenerator进行解码
SourceGenerator.this.onDataReadyInternal(toStart, data);
}
}
......
}
}
// 2.17 获取图片数据 @HttpUrlFetcher.java
public void loadData(@NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) {
......
try {
// -->2.18 网络下载图片
InputStream result = this.loadDataWithRedirects(this.glideUrl.toURL(), 0, (URL)null, this.glideUrl.getHeaders());
callback.onDataReady(result);
} catch (IOException var9) {...}
......
}
// 2.18 使用HttpURLConnection下载网络图片 @HttpUrlFetcher.java
private InputStream loadDataWithRedirects(...) throws IOException {
if (redirects >= 5) {
//设置最大重定向次数为5次
throw new HttpException("Too many (> 5) redirects!");
} else {
......
this.urlConnection.setConnectTimeout(this.timeout);
this.urlConnection.setReadTimeout(this.timeout);
this.urlConnection.setUseCaches(false);
this.urlConnection.setDoInput(true);
this.urlConnection.setInstanceFollowRedirects(false);
this.urlConnection.connect();
this.stream = this.urlConnection.getInputStream();
if (this.isCancelled) {
return null;
} else {
int statusCode = this.urlConnection.getResponseCode();
if (isHttpOk(statusCode)) {
// -->2.19请求成功,获取图片数据
return this.getStreamForSuccessfulRequest(this.urlConnection);
} else if (isHttpRedirect(statusCode)) {
......
// 重定向次数加1
return this.loadDataWithRedirects(redirectUrl, redirects + 1, url, headers);
}
} else if (statusCode == -1) {
throw new HttpException(statusCode);
} else {
throw new HttpException(this.urlConnection.getResponseMessage(), statusCode);
}
}
}
}
// 2.19 获取数据流 @HttpUrlFetcher.java
private InputStream getStreamForSuccessfulRequest(HttpURLConnection urlConnection) throws IOException {
if (TextUtils.isEmpty(urlConnection.getContentEncoding())) {
int contentLength = urlConnection.getContentLength();
this.stream = ContentLengthInputStream.obtain(urlConnection.getInputStream(), (long)contentLength);
} else {
if (Log.isLoggable("HttpUrlFetcher", 3)) {
Log.d("HttpUrlFetcher", "Got non empty content encoding: " + urlConnection.getContentEncoding());
}
// 获取数据流
this.stream = urlConnection.getInputStream();
}
return this.stream;
}
终于到了图篇下载的地方,我们最后获取的是数据流,接下来的步骤是数据流解码。
6.返回数据流解码
// -->3.1 返回数据流到SourceGenerator @SourceGenerator.java
void onDataReadyInternal(LoadData<?> loadData, Object data) {
DiskCacheStrategy diskCacheStrategy = this.helper.getDiskCacheStrategy();
if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) {
this.dataToCache = data;
this.cb.reschedule();
} else {
// --> 3.2 回到DecodeJob继续处理,会调用到decodeFromRetrievedData处理
this.cb.onDataFetcherReady(loadData.sourceKey, data, loadData.fetcher, loadData.fetcher.getDataSource(), this.originalKey);
}
}
// 3.2 处理返回数据 @DecodeJob.java
private void decodeFromRetrievedData() {
......
try {
// -->3.3 在decodeFromFetcher中调用decodeFromFetcher处理,从数据中解码得到资源
resource = this.decodeFromData(this.currentFetcher, this.currentData, this.currentDataSource);
} catch (GlideException var3) {
var3.setLoggingDetails(this.currentAttemptingKey, this.currentDataSource);
this.throwables.add(var3);
}
if (resource != null) {
// -->4.1 编码和发布资源
this.notifyEncodeAndRelease(resource, this.currentDataSource);
} else {
this.runGenerators();
}
}
// 3.3 @DecodeJob.java
private <Data> Resource<R> decodeFromFetcher(Data data, DataSource dataSource) throws GlideException {
LoadPath<Data, ?, R> path = this.decodeHelper.getLoadPath(data.getClass());
// -->3.4 将解码任务分发给LoadPath
return this.runLoadPath(data, dataSource, path);
}
// 3.4 将解码任务分发给LoadPath
private <Data, ResourceType> Resource<R> runLoadPath(...) throws GlideException {
Options options = this.getOptionsWithHardwareConfig(dataSource);
// 将数据打包到Rewinder对象中,根据data的类型获取对应的rewinder,这里为ByteBufferRewinder
DataRewinder rewinder = this.glideContext.getRegistry().getRewinder(data);
Resource var6;
try {
// -->3.5 LoadPath.load -> LoadPath.loadWithExceptionList -> DecodePath.decodeResource ->
// DecodePath.decodeResourceWithList
var6 = path.load(rewinder, options, this.width, this.height, new DecodeJob.DecodeCallback(dataSource));
} finally {
rewinder.cleanup();
}
return var6;
}
// 3.5 @DecodePath.java
private Resource<ResourceType> decodeResourceWithList(...) throws GlideException {
......
try {
DataType data = rewinder.rewindAndGet();
if (decoder.handles(data, options)) {
data = rewinder.rewindAndGet();
// -->3.6根据dataType使用对应的decoder,这里decoder是ByteBufferBitmapDecoder
result = decoder.decode(data, width, height, options);
}
}
......
if (result == null) {
// 如果找不到合适的decoder抛出异常,回到LoadPath.loadWithExceptionList中用下一个DecodePath处理
throw new GlideException(this.failureMessage, new ArrayList(exceptions));
} else {
return result;
}
}
// 3.6 对数据进行处理 @ByteBufferBitmapDecoder.java
public Resource<Bitmap> decode(...) throws IOException {
InputStream is = ByteBufferUtil.toStream(source);
// -->3.7 使用downsampler对流数据进行解码和图像处理等,并封装为Resource<Bitmap>对象返回
return this.downsampler.decode(is, width, height, options);
}
// 3.7 使用downsampler对流数据进行解码和图像处理等 @Downsampler.java
private Resource<Bitmap> decode(...) throws IOException {
BitmapResource var14;
try {
//Bitmap处理
Bitmap result = this.decodeFromWrappedStreams(imageReader, bitmapFactoryOptions, downsampleStrategy, decodeFormat, preferredColorSpace, isHardwareConfigAllowed, requestedWidth, requestedHeight, fixBitmapToRequestedDimensions, callbacks);
//打包为Resource<Bitmap>对象返回
var14 = BitmapResource.obtain(result, this.bitmapPool);
} finally {
releaseOptions(bitmapFactoryOptions);
this.byteArrayPool.put(bytesForOptions);
}
return var14;
}
通过上面步骤,基本解码流程就结束了,加下来进入解码和发布流程
7.解码和发布
解码和发布,就是将Bitmap显示到ImageView,这里的入口在notifyEncodeAndRelease中,代码回到DecodeJob中。
// 4.1 解码和发布流程入口 @DecodeJob.java
private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {
......
// -->4.2 开始解码和发布
this.notifyComplete((Resource)result, dataSource);
// 设置stage为ENCODE
this.stage = DecodeJob.Stage.ENCODE;
......
}
//4.2 开始解码和发布 @DecodeJob.java
private void notifyComplete(Resource<R> resource, DataSource dataSource) {
this.setNotifiedOrThrow();
// -->4.3 回调EngineJob.onResourceReady
this.callback.onResourceReady(resource, dataSource);
}
// 4.3 @EngineJob.java
public void onResourceReady(Resource<R> resource, DataSource dataSource) {
synchronized(this) {
this.resource = resource;
this.dataSource = dataSource;
}
// -->4.4
this.notifyCallbacksOfResult();
}
// 4.4 @EngineJob.java
void notifyCallbacksOfResult() {
......
// -->4.5
while(var4.hasNext()) {
EngineJob.ResourceCallbackAndExecutor entry = (EngineJob.ResourceCallbackAndExecutor)var4.next();
entry.executor.execute(new EngineJob.CallResourceReady(entry.cb));
}
}
//4.5 @EngineJob.java
static final class ResourceCallbackAndExecutor {
while(var4.hasNext()) {
EngineJob.ResourceCallbackAndExecutor entry = (EngineJob.ResourceCallbackAndExecutor)var4.next();
entry.executor.execute(new EngineJob.CallResourceReady(entry.cb)); //-->4.6
}
}
//4.6 @EngineJob.java
private class CallResourceReady implements Runnable {
public void run() {
......
// -->4.7
EngineJob.this.callCallbackOnResourceReady(this.cb);
......
}
}
//4.7 @EngineJob.java
void callCallbackOnResourceReady(ResourceCallback cb) {
try {
//-->4.8 这里的回调cb指的传的就是SingleRequest,在2.6中 SingleRequest中把自身作为倒数第二个参数传入engine.load中
cb.onResourceReady(this.engineResource, this.dataSource);
} catch (Throwable var3) {
throw new CallbackException(var3);
}
}
// 4.8 @SingleRequest.java
private void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {
......
if (!anyListenerHandledUpdatingTarget) {
Transition<? super R> animation = animationFactory.build(dataSource, isFirstResource);
//-->4.9 这里的target便是我们调用之初建立的BitmapImageViewTarget,具体的实现方法在其父类ImageViewTarget中
target.onResourceReady(result, animation);
}
......
}
// 4.9 @ImageViewTarget.java
@Override
public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {
if (transition == null || !transition.transition(resource, this)) {
setResourceInternal(resource); //-->4.10
} else {
maybeUpdateAnimatable(resource);
}
}
//4.10 @ImageViewTarget.java
private void setResourceInternal(@Nullable Z resource) {
//-->4.11 抽象方法,具体实现在子类BitmapImageViewTarget中
setResource(resource);
maybeUpdateAnimatable(resource);
}
//4.11 @BitmapImageView.java
@Override
protected void setResource(Bitmap resource) {
//终于看到了Bitmap设置到imageView上!
view.setImageBitmap(resource);
}
从上面分析流程可知,Gilde大多数的处理流程都在into
方法中执行,请求,数据,编码解码,以及最后的显示,这份源码值得我们多读几次,细细品味。
文章虽然很长,但是我还是决定不分篇,以保证加载流程阅读的完整度,也方便后期检索方便。很感谢看到最后的各位~