摘要
Glide流程三步曲with
、load
、into
三个函数,完成一次Glide请求。with
的主要工作是首次创建Glide单例,并装配Glide各种配置参数和创建相关实例,这些都会在into
函数中被使用到,第二个要点就是与Fragment的生命周期绑定,让Glide请求能感应到生命周期的变化,从而可以进行暂停,恢复,发起请求的一下操作。load
函数则是构建本次Glide
请求的相关信息,例如RequestBuilder
、RequestOptions
等。into
函数则是Glide的核心,包括缓存,解码,采样转化,资源获取等等。
Glide源码分析基于Glide 4.12.0
:
1 2 implementation 'com.github.bumptech.glide:glide:4.12.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
由于源码分析阶段会有很多分支,很多的类型,所以在一些点会基于下面例子分析。
1 2 val url="http//:www.xxm-sz.githu.io/test.png" Glide.with(this ).load(url).into(imageView)
with
函数
Glide单例的创建
Glide.with
有很多重载函数。这里以Activity
为例分析。
1 2 3 public static RequestManager with (@NonNull FragmentActivity activity) { return getRetriever(activity).get(activity); }
Glide.with
的所有重载函数中的getRetriever
都是调用getRetriever
来生成Glide
单例。
1 2 3 4 5 @NonNull private static RequestManagerRetriever getRetriever (@Nullable Context context) { ...... return Glide.get(context).getRequestManagerRetriever(); }
Glide.get(context)
通过双重检查 实现单例模式,生成Glide实例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public static Glide get (@NonNull Context context) { if (glide == null ) { GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules(context.getApplicationContext()); synchronized (Glide.class) { if (glide == null ) { checkAndInitializeGlide(context, annotationGeneratedModule); } } } return glide; }
在Application
模块中,可创建一个添加有 @GlideModule
注解,继承自 AppGlideModule
的类,这样就可以通过流式API使用Glide。GeneratedAppGlideModule
也就是对应该注解类的。
步骤1: getAnnotationGeneratedGlideModules
函数主要通过反射获取我们AppGlideModule
实例。
1 2 3 4 5 6 7 8 9 10 11 private static GeneratedAppGlideModule getAnnotationGeneratedGlideModules (Context context) { GeneratedAppGlideModule result = null ; ... Class<GeneratedAppGlideModule> clazz = (Class<GeneratedAppGlideModule>) Class.forName("com.bumptech.glide.GeneratedAppGlideModuleImpl" ); result = clazz.getDeclaredConstructor(Context.class).newInstance(context.getApplicationContext()); ... return result; }
步骤2: checkAndInitializeGlide
函数最终会调用到initializeGlide
函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 private static void initializeGlide ( @NonNull Context context, @NonNull GlideBuilder builder, @Nullable GeneratedAppGlideModule annotationGeneratedModule) { Context applicationContext = context.getApplicationContext(); List<com.bumptech.glide.module .GlideModule> manifestModules = Collections.emptyList(); if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) { manifestModules = new ManifestParser(applicationContext).parse(); } if (annotationGeneratedModule != null && !annotationGeneratedModule.getExcludedModuleClasses().isEmpty()) { Set<Class<?>> excludedModuleClasses = annotationGeneratedModule.getExcludedModuleClasses(); Iterator<com.bumptech.glide.module .GlideModule> iterator = manifestModules.iterator(); while (iterator.hasNext()) { com.bumptech.glide.module .GlideModule current = iterator.next(); if (!excludedModuleClasses.contains(current.getClass())) { continue ; } iterator.remove(); } } ... RequestManagerRetriever.RequestManagerFactory factory = annotationGeneratedModule != null ? annotationGeneratedModule.getRequestManagerFactory() : null ; builder.setRequestManagerFactory(factory); for (com.bumptech.glide.module .GlideModule module : manifestModules) { module .applyOptions(applicationContext, builder); } if (annotationGeneratedModule != null ) { annotationGeneratedModule.applyOptions(applicationContext, builder); } Glide glide = builder.build(applicationContext); for (com.bumptech.glide.module .GlideModule module : manifestModules) { try { module .registerComponents(applicationContext, glide, glide.registry); } catch (AbstractMethodError e) { ... } } if (annotationGeneratedModule != null ) { annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry); } applicationContext.registerComponentCallbacks(glide); Glide.glide = glide; }
其实在没有定义GlideModule
情况下,这段代码只有一个核心点,通过GlideBuilder
构建Glide,为Glide创建默认的属性,例如缓存,引擎等等。创建的对象在后续into
函数中被大量使用到。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 Glide build (@NonNull Context context) { if (sourceExecutor == null ) { sourceExecutor = GlideExecutor.newSourceExecutor(); } if (diskCacheExecutor == null ) { diskCacheExecutor = GlideExecutor.newDiskCacheExecutor(); } if (animationExecutor == null ) { animationExecutor = GlideExecutor.newAnimationExecutor(); } 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); } GlideExperiments experiments = glideExperimentsBuilder.build(); RequestManagerRetriever requestManagerRetriever = new RequestManagerRetriever(requestManagerFactory, experiments); return new Glide( context, engine, memoryCache, bitmapPool, arrayPool, requestManagerRetriever, connectivityMonitorFactory, logLevel, defaultRequestOptionsFactory, defaultTransitionOptions, defaultRequestListeners, experiments); }
RequestManager
的创建
RequestManager
的创建涉及到与Application
或Fragment
生命周期的绑定,RequestManager
可以用来开始和停止、管理本次Glide请求。
再回到getRetriever(activity).get(activity)
的get
函数。
1 2 3 4 5 6 7 8 9 10 11 @NonNull public RequestManager get (@NonNull FragmentActivity activity) { if (Util.isOnBackgroundThread()) { return get(activity.getApplicationContext()); } else { assertNotDestroyed(activity); frameWaiter.registerSelf(activity); FragmentManager fm = activity.getSupportFragmentManager(); return supportFragmentGet(activity, fm, null , isActivityVisible(activity)); } }
通过Util.isOnBackgroundThread()
判断是否后台线程,如果不是则通过supportFragmentGet
创建RequestManager
。否则通过get(activity)
的重载函数get(Context)
获取RequestManager
。查看get()
的其他重载函数,如果在后台线程或者参数为ApplicationContext
上下文,都通过getApplicationManager(context)
来生成RequestManager
,而其他情况则是supportFragmentGet
函数。
supportFragmentGet
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 private RequestManager supportFragmentGet ( @NonNull Context context, @NonNull FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) { SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint); RequestManager requestManager = current.getRequestManager(); if (requestManager == null ) { Glide glide = Glide.get(context); requestManager = factory.build( glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context); if (isParentVisible) { requestManager.onStart(); } current.setRequestManager(requestManager); } return requestManager; }
步骤1 :通过getSupportRequestManagerFragment
函数创建SupportRequestManagerFragment
对象。SupportRequestManagerFragment
是Fragment
的子类,该Fragment
对象是没有视图,作为发起Glide
请求的Activity
或Fragment
的子Fragment
,将持有RequestManager
实例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 private SupportRequestManagerFragment getSupportRequestManagerFragment ( @NonNull final FragmentManager fm, @Nullable Fragment parentHint) { SupportRequestManagerFragment current = (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG); if (current == null ) { current = pendingSupportRequestManagerFragments.get(fm); if (current == null ) { current = new SupportRequestManagerFragment(); current.setParentFragmentHint(parentHint); pendingSupportRequestManagerFragments.put(fm, current); fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss(); handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget(); } } return current; }
先通过FRAGMENT_TAG
标签在FragmentMananger
中查找是否有已添加的Fragment
实例。没有的话,在endingSupportRequestManagerFragments
查找,endingSupportRequestManagerFragments
是HashMap
类型的,以FragmentMananger
为key
,SupportRequestManagerFragment
为Value
。没有的话,则新建实例,并添加pendingSupportRequestManagerFragments
中,并通过FragmentMananger
提交。这个创建逻辑也保证了在一个Activity
中所发起的所有Glide请求都只有一个空白Fragment
。
在创建SupportRequestManagerFragment
时候,会创建一个新的ActivityFragmentLifecycle
,用于跟踪和监听Fragment
的生命周期事件。
**步骤2:**在步骤1获取到了Fragment
后,获取其持有的RequestManager
,如果Fragment
是新建获得,那肯定是没有,只能通过新建RequestManager
。
1 factory.build(glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
这里的factory
是RequestManagerFactory
,在构建Glide单例的时候会创建,默认情况下是DEFAULT_FACTORY
。在创建RequestManager
时不仅监听Fragment
生命周期的变化,还会监听网络连接变化。
1 2 3 4 5 6 7 8 9 10 11 12 private static final RequestManagerFactory DEFAULT_FACTORY = new RequestManagerFactory() { @NonNull @Override public RequestManager build ( @NonNull Glide glide, @NonNull Lifecycle lifecycle, @NonNull RequestManagerTreeNode requestManagerTreeNode, @NonNull Context context) { return new RequestManager(glide, lifecycle, requestManagerTreeNode, context); } };
所以,当Fragment
生命周期发生变化或者网络发生变化时,RequestManager
根据不同场景去管理本次Glide
请求。
在View
场景下的Glide.with()
稍微麻烦点,需要根据View.getContext()
得到Context
的类型,去查找不同的get()
函数重载。而Fragment
场景下,与Actvity
发起的Glide请求大同小异。
getApplicationManager
在后台线程或ApplicationContext
场景下,通过getApplicationManager(context)
创建RequestManager
。通过下面代码可以看到,RequestManager
直接与Application
的生命周期绑定。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 private RequestManager getApplicationManager (@NonNull Context context) { if (applicationManager == null ) { synchronized (this ) { if (applicationManager == null ) { Glide glide = Glide.get(context.getApplicationContext()); applicationManager = factory.build( glide, new ApplicationLifecycle(), new EmptyRequestManagerTreeNode(), context.getApplicationContext()); } } } return applicationManager; }
而ApplicationLifecycle
基本什么都没做,因为Glide请求与Application绑定,意味随着Applilcation
的消亡而消亡。
到这里,Glide.with()
的分析就完毕了,主要创建Glide
单例,和为Glide
请求创建RequestManager
。在后台线程或者ApplicationContext
情况下创建的RequestManager
是与Application
的生命周期绑定的,而其他情况下,通过创建一个无视图的Fragment
的,并将RequestManager
与其生命周期绑定。
配置:load
load
函数也有很多重载函数。
1 2 3 public RequestBuilder<XXX> load (@Nullable XXX xxx) { return asDrawable().load(xxx); }
所以看一下asDrawable()
函数。
1 2 3 4 5 6 7 8 public RequestBuilder<Drawable> asDrawable () { return as(Drawable.class); } public <ResourceType> RequestBuilder<ResourceType> as ( @NonNull Class<ResourceType> resourceClass) { return new RequestBuilder<>(glide, this , resourceClass, context); }
可见,asDrawable
函数主要是创建了RequestBuilder
对象,RequestBuilder
是BaseRequestOptions
的子类,用于保存Glide通用资源类型的配置参数。BaseRequestOptions
的另外一个子类RequestOptions
,通常用来配置一次独立的Glide请求配置参数。注意这里的as
的参数Drawable.class
,表明的是本次请求的目标资源是Drawable.class
,即后续分析会看到transcodeClass
就是该Drawable.class
。仅下载情况是File.class
,Gif图情况下是GifDrawable.class
。
继续看RequestBuilder
的load
函数。
1 2 3 4 5 6 7 8 9 10 11 12 public RequestBuilder<TranscodeType> load (@Nullable String string) { return loadGeneric(string); } private RequestBuilder<TranscodeType> loadGeneric (@Nullable Object model) { if (isAutoCloneEnabled()) { return clone().loadGeneric(model); } this .model = model; isModelSet = true ; return selfOrThrowIfLocked(); }
主要是将我们设置的资源:Glide.with(context).load(xxx)
中的xxx
设置给RequestBuilder
的model
属性,并将isModelSet
设置true
。后续分析中modelClass
就是这里xxx
的类型。
假如这里load(drawable)
或者load(bitmap)
,会有多一个步骤:
1 2 3 public RequestBuilder<TranscodeType> load (@Nullable Drawable drawable) { return loadGeneric(drawable).apply(diskCacheStrategyOf(DiskCacheStrategy.NONE)); }
也就是多了apply(options)
,跟我们自定义Glide请求配置是一致的。这里也会将RequestOptions
缓存起来。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 public T apply (@NonNull BaseRequestOptions<?> o) { if (isAutoCloneEnabled) { return clone().apply(o); } BaseRequestOptions<?> other = o; if (isSet(other.fields, SIZE_MULTIPLIER)) { sizeMultiplier = other.sizeMultiplier; } if (isSet(other.fields, USE_UNLIMITED_SOURCE_GENERATORS_POOL)) { useUnlimitedSourceGeneratorsPool = other.useUnlimitedSourceGeneratorsPool; } if (isSet(other.fields, USE_ANIMATION_POOL)) { useAnimationPool = other.useAnimationPool; } if (isSet(other.fields, DISK_CACHE_STRATEGY)) { diskCacheStrategy = other.diskCacheStrategy; } if (isSet(other.fields, PRIORITY)) { priority = other.priority; } if (isSet(other.fields, ERROR_PLACEHOLDER)) { errorPlaceholder = other.errorPlaceholder; errorId = 0 ; fields &= ~ERROR_ID; } if (isSet(other.fields, ERROR_ID)) { errorId = other.errorId; errorPlaceholder = null ; fields &= ~ERROR_PLACEHOLDER; } if (isSet(other.fields, PLACEHOLDER)) { placeholderDrawable = other.placeholderDrawable; placeholderId = 0 ; fields &= ~PLACEHOLDER_ID; } if (isSet(other.fields, PLACEHOLDER_ID)) { placeholderId = other.placeholderId; placeholderDrawable = null ; fields &= ~PLACEHOLDER; } if (isSet(other.fields, IS_CACHEABLE)) { isCacheable = other.isCacheable; } if (isSet(other.fields, OVERRIDE)) { overrideWidth = other.overrideWidth; overrideHeight = other.overrideHeight; } if (isSet(other.fields, SIGNATURE)) { signature = other.signature; } if (isSet(other.fields, RESOURCE_CLASS)) { resourceClass = other.resourceClass; } if (isSet(other.fields, FALLBACK)) { fallbackDrawable = other.fallbackDrawable; fallbackId = 0 ; fields &= ~FALLBACK_ID; } if (isSet(other.fields, FALLBACK_ID)) { fallbackId = other.fallbackId; fallbackDrawable = null ; fields &= ~FALLBACK; } if (isSet(other.fields, THEME)) { theme = other.theme; } if (isSet(other.fields, TRANSFORMATION_ALLOWED)) { isTransformationAllowed = other.isTransformationAllowed; } if (isSet(other.fields, TRANSFORMATION_REQUIRED)) { isTransformationRequired = other.isTransformationRequired; } if (isSet(other.fields, TRANSFORMATION)) { transformations.putAll(other.transformations); isScaleOnlyOrNoTransform = other.isScaleOnlyOrNoTransform; } if (isSet(other.fields, ONLY_RETRIEVE_FROM_CACHE)) { onlyRetrieveFromCache = other.onlyRetrieveFromCache; } if (!isTransformationAllowed) { transformations.clear(); fields &= ~TRANSFORMATION; isTransformationRequired = false ; fields &= ~TRANSFORMATION_REQUIRED; isScaleOnlyOrNoTransform = true ; } fields |= other.fields; options.putAll(other.options); return selfOrThrowIfLocked(); }
也就是说load
函数的主要工作是配置Glide请求的一些参数。
核心:into
into
函数也有很多重载函数,但我们最常用的就是into(ImageView)
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 public ViewTarget<ImageView, TranscodeType> into (@NonNull ImageView view) { ... BaseRequestOptions<?> requestOptions = this ; if (!requestOptions.isTransformationSet() && requestOptions.isTransformationAllowed() && view.getScaleType() != null ) { switch (view.getScaleType()) { case CENTER_CROP: requestOptions = requestOptions.clone().optionalCenterCrop(); break ; case CENTER_INSIDE: requestOptions = requestOptions.clone().optionalCenterInside(); break ; case FIT_CENTER: case FIT_START: case FIT_END: requestOptions = requestOptions.clone().optionalFitCenter(); break ; case FIT_XY: requestOptions = requestOptions.clone().optionalCenterInside(); break ; case CENTER: case MATRIX: default : } } return into( glideContext.buildImageViewTarget(view, transcodeClass), null , requestOptions, Executors.mainThreadExecutor()); }
从这里看到Glide只处理View ScaleType
的CENTER_CROP
、CENTER_INSIDE、
FIT_XY
,而FIT_CENTER
、FIT_START
、FIT_END
都统一通过optionalFitCenter
处理,而CENTER
和MATRIX
则直接忽略。然后调用into
另外一个重载函数。先通过glideContext.buildImageViewTarget
将ImageView
封装成ViewTarget
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public <X> ViewTarget<ImageView, X> buildImageViewTarget ( @NonNull ImageView imageView, @NonNull Class<X> transcodeClass) { return imageViewTargetFactory.buildTarget(imageView, transcodeClass); } 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)" ); } } }
通过ImageViewTargetFactory
工厂的buildTarget
函数可以发现ViewTarget
有两种类型:BitmapImageViewTraget
和DrawableImageViewTarget
。两者都是ImageViewTarget
的子类,前者用于展示Bitmap
,后者用于展示Drawable
。另外一个子类ThumbnailImageViewTarget
,用于在固定尺寸的ImageView
展示多张图片,避免额外调用requestLayout
,常用场景就是列表的缩略图设置。
into
函数的第三个参数Executors.mainThreadExecutor()
,在主线程执行的线程池,也就是调用线程池的execute
函数时,将runable
对象通过handler post
到主线程的队列,这样就在主线程执行了该任务。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public static Executor mainThreadExecutor () { return MAIN_THREAD_EXECUTOR; } public static Executor mainThreadExecutor () { return MAIN_THREAD_EXECUTOR; } private static final Executor MAIN_THREAD_EXECUTOR = new Executor() { @Override public void execute (@NonNull Runnable command) { Util.postOnUiThread(command); } }; public static void postOnUiThread (Runnable runnable) { getUiThreadHandler().post(runnable); } private static Handler getUiThreadHandler () { if (mainThreadHandler == null ) { synchronized (Util.class) { if (mainThreadHandler == null ) { mainThreadHandler = new Handler(Looper.getMainLooper()); } } } return mainThreadHandler; }
继续看看into
的重载函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 private <Y extends Target<TranscodeType>> Y into ( @NonNull Y target, @Nullable RequestListener<TranscodeType> targetListener, BaseRequestOptions<?> options, Executor callbackExecutor) { Preconditions.checkNotNull(target); if (!isModelSet) { throw new IllegalArgumentException("You must call #load() before calling #into()" ); } Request request = buildRequest(target, targetListener, options, callbackExecutor); Request previous = target.getRequest(); if (request.isEquivalentTo(previous) && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) { if (!Preconditions.checkNotNull(previous).isRunning()) { previous.begin(); } return target; } requestManager.clear(target); target.setRequest(request); requestManager.track(target, request); return target; }
步骤1: 通过buildRequest
创建了Request
对象,Request
代表了一次为目标Target
加载图片资源resource
的Glide
请求。
SingleRequest的创建
通过buildRequest
函数会创建一个Request
对象,该对象是Request
的子类实例,可能ThumbnailRequestCoordinator
或ErrorRequestCoordinator
也有可能是SingleRequest
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 private Request buildRequest ( Target<TranscodeType> target, @Nullable RequestListener<TranscodeType> targetListener, BaseRequestOptions<?> requestOptions, Executor callbackExecutor) { return buildRequestRecursive( new Object(), target, targetListener, null , transitionOptions, requestOptions.getPriority(), requestOptions.getOverrideWidth(), requestOptions.getOverrideHeight(), requestOptions, callbackExecutor); }
调用了buildRequestRecursive
函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 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) { ErrorRequestCoordinator errorRequestCoordinator = null ; if (errorBuilder != null ) { errorRequestCoordinator = new ErrorRequestCoordinator(requestLock, parentCoordinator); parentCoordinator = errorRequestCoordinator; } Request mainRequest = buildThumbnailRequestRecursive( requestLock, targ et, targetListener, parentCoordinator, transitionOptions, priority, overrideWidth, overrideHeight, requestOptions, callbackExecutor); if (errorRequestCoordinator == null ) { return mainRequest; } int errorOverrideWidth = errorBuilder.getOverrideWidth(); int errorOverrideHeight = errorBuilder.getOverrideHeight(); if (Util.isValidDimensions(overrideWidth, overrideHeight) && !errorBuilder.isValidOverride()) { errorOverrideWidth = requestOptions.getOverrideWidth(); errorOverrideHeight = requestOptions.getOverrideHeight(); } Request errorRequest = errorBuilder.buildRequestRecursive( requestLock, target, targetListener, errorRequestCoordinator, errorBuilder.transitionOptions, errorBuilder.getPriority(), errorOverrideWidth, errorOverrideHeight, errorBuilder, callbackExecutor); errorRequestCoordinator.setRequests(mainRequest, errorRequest); return errorRequestCoordinator; }
步骤A: buildThumbnailRequestRecursive
创建了Request
,这里返回的Request
有两种可能,一种是设置了加载缩略图和主图的,返回的ThumbnailRequestCoordinator
,会协调好缩略图SingleRequest
和主图SingleRequest
的同时加载。另外一种是SingleRequest
,单单加载主图,两者都是Request
的子类。
如果有设置在发生错误时的请求也会在这里配置该请求,通过后面的分析,也就是每个RequestBuilder
(不仅是主图,也可以是缩略图,错误提示图等)都会创建一个SingleRequest
。
接着看buildThumbnailRequestRecursive
函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 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 (thumbnailBuilder != null ) { if (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()" ); } TransitionOptions<?, ? super TranscodeType> thumbTransitionOptions = thumbnailBuilder.transitionOptions; if (thumbnailBuilder.isDefaultTransitionOptionsSet) { thumbTransitionOptions = transitionOptions; } Priority thumbPriority = thumbnailBuilder.isPrioritySet() ? thumbnailBuilder.getPriority() : getThumbnailPriority(priority); int thumbOverrideWidth = thumbnailBuilder.getOverrideWidth(); int thumbOverrideHeight = thumbnailBuilder.getOverrideHeight(); if (Util.isValidDimensions(overrideWidth, overrideHeight) && !thumbnailBuilder.isValidOverride()) { thumbOverrideWidth = requestOptions.getOverrideWidth(); thumbOverrideHeight = requestOptions.getOverrideHeight(); } ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(requestLock, parentCoordinator); Request fullRequest = obtainRequest( requestLock, target, targetListener, requestOptions, coordinator, transitionOptions, priority, overrideWidth, overrideHeight, callbackExecutor); isThumbnailBuilt = true ; Request thumbRequest = thumbnailBuilder.buildRequestRecursive( requestLock, target, targetListener, coordinator, thumbTransitionOptions, thumbPriority, thumbOverrideWidth, thumbOverrideHeight, thumbnailBuilder, callbackExecutor); isThumbnailBuilt = false ; coordinator.setRequests(fullRequest, thumbRequest); return coordinator; } else if (thumbSizeMultiplier != null ) { ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(requestLock, parentCoordinator); Request fullRequest = obtainRequest( requestLock, target, targetListener, requestOptions, coordinator, transitionOptions, priority, overrideWidth, overrideHeight, callbackExecutor); BaseRequestOptions<?> thumbnailOptions = requestOptions.clone().sizeMultiplier(thumbSizeMultiplier); Request thumbnailRequest = obtainRequest( requestLock, target, targetListener, thumbnailOptions, coordinator, transitionOptions, getThumbnailPriority(priority), overrideWidth, overrideHeight, callbackExecutor); coordinator.setRequests(fullRequest, thumbnailRequest); return coordinator; } else { return obtainRequest( requestLock, target, targetListener, requestOptions, parentCoordinator, transitionOptions, priority, overrideWidth, overrideHeight, callbackExecutor); } }
由于没有设置缩略图,直接走else
分支,通过obtainRequest
获得Request
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 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); } }
通过SingleRequest.obtain
函数返回了Request
对象。obtain
函数直接创建了Request
的子类SingleRequest
对象。
这里buildRequest
函数小结一下:
如果设置了缩略图,返回ThumbnailRequestCoordinator
对象,包含了主图和缩图两个独立的SingleRequest
。
如果设置了错误占位图,返回的是ErrorRequestCoordinator
,包含了上一步返回的Request
对象和占位图的SingleRequest
对象,
如果上两步都没有设置,返回主图的SingleRequest
。
继续分析into
函数的步骤2:
requestManager.track
track
函数分别用了TragetTrack
和RequestTrack
跟踪本次请求的traget
和request
对象。RequestTrack
主要用于跟踪,取消和重启正在运行中的,已完成或者失败的请求。TragetTrack
则持有当前活跃的RequestManager
以及转发绑定的生命周期事件。
1 2 3 4 5 6 synchronized void track (@NonNull Target<?> target, @NonNull Request request) { targetTracker.track(target); requestTracker.runRequest(request); }
看看RequestTrack
的runRequest
函数。
1 2 3 4 5 6 7 8 9 10 11 12 public void runRequest (@NonNull Request request) { requests.add(request); if (!isPaused) { request.begin(); } else { request.clear(); if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "Paused, delaying request" ); } pendingRequests.add(request); } }
看看request.begin()
函数。我们这里直接定位到SingleRequest
的begin
函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Override public void begin () { synchronized (requestLock) { ...... status = Status.WAITING_FOR_SIZE; if (Util.isValidDimensions(overrideWidth, overrideHeight)) { onSizeReady(overrideWidth, overrideHeight); } else { target.getSize(this ); } if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE) && canNotifyStatusChanged()) { target.onLoadStarted(getPlaceholderDrawable()); } } }
定位到target.getSize(this)
获取Target
尺寸大小,这里的this
是SizeReadyCallback
。也就是在获取到目标尺寸之后,通过SizeReadyCallback
对象回调。这里的Target
对象直接定位到ViewTarget
。
1 2 3 public void getSize (@NonNull SizeReadyCallback cb) { sizeDeterminer.getSize(cb); }
通过getSize
函数的注释,就知道了Glide如何去获取尺寸的。
直接获取View的宽高,如果都大于零或者等于原始尺寸,说明已经能获取到了。
直接获取View的LayotuParams,如果都大于零或者等于原始尺寸,说明已经能获取到了。
添加addOnPreDrawListener
监听。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 void getSize (@NonNull SizeReadyCallback cb) { int currentWidth = getTargetWidth(); int currentHeight = getTargetHeight(); if (isViewStateAndSizeValid(currentWidth, currentHeight)) { cb.onSizeReady(currentWidth, currentHeight); return ; } if (!cbs.contains(cb)) { cbs.add(cb); } if (layoutListener == null ) { ViewTreeObserver observer = view.getViewTreeObserver(); layoutListener = new SizeDeterminerLayoutListener(this ); observer.addOnPreDrawListener(layoutListener); } }
所以通过三个步骤,最终会获得ViewTarget的宽高,并通过SizeReadyCallback
对象的onSizeReady
函数回调。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 @Override public void onSizeReady (int width, int height) { stateVerifier.throwIfRecycled(); synchronized (requestLock) { if (status != Status.WAITING_FOR_SIZE) { return ; } status = Status.RUNNING; float sizeMultiplier = requestOptions.getSizeMultiplier(); this .width = maybeApplySizeMultiplier(width, sizeMultiplier); this .height = maybeApplySizeMultiplier(height, sizeMultiplier); loadStatus = engine.load( glideContext, model, requestOptions.getSignature(), this .width, this .height, requestOptions.getResourceClass(), transcodeClass, priority, requestOptions.getDiskCacheStrategy(), requestOptions.getTransformations(), requestOptions.isTransformationRequired(), requestOptions.isScaleOnlyOrNoTransform(), requestOptions.getOptions(), requestOptions.isMemoryCacheable(), requestOptions.getUseUnlimitedSourceGeneratorsPool(), requestOptions.getUseAnimationPool(), requestOptions.getOnlyRetrieveFromCache(), this , callbackExecutor); if (status != Status.RUNNING) { loadStatus = null ; } } }
所以onSizeReady
最重要的点就是调用了engine.load
开始本次Glide
请求。
engine.load
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 public <R> LoadStatus load ( GlideContext glideContext, Object model, Key signature, int width, int height, Class<?> resourceClass, Class<R> transcodeClass, Priority priority, DiskCacheStrategy diskCacheStrategy, Map<Class<?>, Transformation<?>> transformations, boolean isTransformationRequired, boolean isScaleOnlyOrNoTransform, Options options, boolean isMemoryCacheable, boolean useUnlimitedSourceExecutorPool, boolean useAnimationPool, boolean onlyRetrieveFromCache, ResourceCallback cb, Executor callbackExecutor) { long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0 ; EngineKey key = keyFactory.buildKey( model, signature, width, height, transformations, resourceClass, transcodeClass, options); EngineResource<?> memoryResource; synchronized (this ) { memoryResource = loadFromMemory(key, isMemoryCacheable, startTime); if (memoryResource == null ) { return waitForExistingOrStartNewJob( glideContext, model, signature, width, height, resourceClass, transcodeClass, priority, diskCacheStrategy, transformations, isTransformationRequired, isScaleOnlyOrNoTransform, options, isMemoryCacheable, useUnlimitedSourceExecutorPool, useAnimationPool, onlyRetrieveFromCache, cb, callbackExecutor, key, startTime); } } cb.onResourceReady( memoryResource, DataSource.MEMORY_CACHE, false ); return null ; }
步骤1 :调用loadFromMemory
函数从内存获取缓存,如果没有拿到缓存资源,则通过步骤2: waitForExistingOrStartNewJob
函数从磁盘缓存或者网络获取。下节再分享这里的Glide缓存。最后拿到资源,则通过cb.onResourceReady
函数回调,回到SingleRequest
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public void onResourceReady ( Resource<?> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) { stateVerifier.throwIfRecycled(); Resource<?> toRelease = null ; try { synchronized (requestLock) { ...... onResourceReady( (Resource<R>) resource, (R) received, dataSource, isLoadedFromAlternateCacheKey); } } finally { if (toRelease != null ) { engine.release(toRelease); } } }
onResourceReady
这里对一些合法性的检查,然后调用onResourceReady
的重载函数。
1 2 3 4 5 6 private void onResourceReady ( Resource<R> resource, R result, DataSource dataSource, boolean isAlternateCacheKey) { ... target.onResourceReady(result, animation); ... }
重载的onResourceReady
函数这里调用target
的onResourceReady
函数。这里定位到ImageViewTarget
类。
1 2 3 4 5 6 7 public void onResourceReady (@NonNull Z resource, @Nullable Transition<? super Z> transition) { if (transition == null || !transition.transition(resource, this )) { setResourceInternal(resource); } else { maybeUpdateAnimatable(resource); } }
其实无论哪个分支,maybeUpdateAnimatable
函数都会被执行,即判断当前资源是否可执行的动画。如果是的话,则直接开始执行。
1 2 3 4 5 6 7 8 private void maybeUpdateAnimatable (@Nullable Z resource) { if (resource instanceof Animatable) { animatable = (Animatable) resource; animatable.start(); } else { animatable = null ; } }
而setResourceInternal
函数,先调用了setResouce
函数,猜测该函数设置资源给Target
。再调用maybeUpdateAnimatable
函数。
1 2 3 4 private void setResourceInternal (@Nullable Z resource) { setResource(resource); maybeUpdateAnimatable(resource); }
setResource
在ImageViewTarget
是一个抽象方法,看一下它的子类BitmapImageViewTarget
的实现。
1 2 3 protected void setResource (Bitmap resource) { view.setImageBitmap(resource); }
setResource
直接将Bitmap
设置给了ImageView
,那么图片也即将展示出来。
因为忽略了engine.load
加载资源分析,所以into
函数看起来很简单,但Glide的所有核心也正在这一部分,将通过后续文章分析该部分。
总结
简简单单分析了Glide的流程三部曲,每一步是责任分明,创建单例与绑定生命周期,配置参数,开始请求。但这才刚刚开始,后续将更加枯燥无趣,黯然无色。