源码解析
glide的使用就是:
Glide.with(this)
.load(IMG_PATH)
.into(imageView);
1、with()方法
@NonNull
public static RequestManager with(@NonNull Context context) {
return getRetriever(context).get(context);
}
@NonNull
public static RequestManager with(@NonNull Activity activity) {
return getRetriever(activity).get(activity);
}
@NonNull
public static RequestManager with(@NonNull FragmentActivity activity) {
return getRetriever(activity).get(activity);
}
@NonNull
public static RequestManager with(@NonNull Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}
@SuppressWarnings("deprecation")
@Deprecated
@NonNull
public static RequestManager with(@NonNull android.app.Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}
@NonNull
public static RequestManager with(@NonNull View view) {
return getRetriever(view.getContext()).get(view);
}
with方法有多个重载的方法,Context、Activity、FragmentActivity、Fragment、view等。
都通过getRetriever().get()返回了一个RequestManager。
getRetriever(Context context)
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
Preconditions.checkNotNull(
context,
"You cannot start a load on a not yet attached View or a Fragment where getActivity() "
+ "returns null (which usually occurs when getActivity() is called before the Fragment "
+ "is attached or after the Fragment is destroyed).");
return Glide.get(context).getRequestManagerRetriever();
}
这个方法返回了一个RequestManagerRetriever对象。Glide.get(context)这个应该就是一个Glide对象
Glide.get(context)
@NonNull
public static Glide get(@NonNull Context context) {
if (glide == null) {
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context);
}
}
}
return glide;
}
是一个双重判断的单例模式,确保Glide对象的唯一性。checkAndInitializeGlide(context)这个方法就应该是去创建Glide对象
checkAndInitializeGlide(context)
private static void checkAndInitializeGlide(@NonNull Context context) {
if (isInitializing) {
throw new IllegalStateException("You cannot call Glide.get() in registerComponents(),"
+ " use the provided Glide instance instead");
}
isInitializing = true;
initializeGlide(context);
isInitializing = false;
}
initializeGlide(context);
private static void initializeGlide(@NonNull Context context) {
//创建了一个GlideBuilder对象
initializeGlide(context, new GlideBuilder());
}
private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
Context applicationContext = context.getApplicationContext();
GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules();
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;
}
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "AppGlideModule excludes manifest GlideModule: " + current);
}
iterator.remove();
}
}
if (Log.isLoggable(TAG, Log.DEBUG)) {
for (com.bumptech.glide.module.GlideModule glideModule : manifestModules) {
Log.d(TAG, "Discovered GlideModule from manifest: " + glideModule.getClass());
}
}
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 glide = builder.build(applicationContext);
for (com.bumptech.glide.module.GlideModule module : manifestModules) {
module.registerComponents(applicationContext, glide, glide.registry);
}
if (annotationGeneratedModule != null) {
annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);
}
applicationContext.registerComponentCallbacks(glide);
Glide.glide = glide;
}
这个方法很长,主要就是builder.build(applicationContext)方法,一看就知道GlideBuilder使用建造者模式去获取glide对象。
GlideBuilder的build(Context context)
@NonNull
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(),
GlideExecutor.newAnimationExecutor(),
isActiveResourceRetentionAllowed);
}
if (defaultRequestListeners == null) {
defaultRequestListeners = Collections.emptyList();
} else {
defaultRequestListeners = Collections.unmodifiableList(defaultRequestListeners);
}
RequestManagerRetriever requestManagerRetriever =
new RequestManagerRetriever(requestManagerFactory);
return new Glide(
context,
engine,
memoryCache,
bitmapPool,
arrayPool,
requestManagerRetriever,
connectivityMonitorFactory,
logLevel,
defaultRequestOptions.lock(),
defaultTransitionOptions,
defaultRequestListeners,
isLoggingRequestOriginsEnabled);
}
用于生成glide的默认配置,主要是构建线程池(包括sourceExecutor ,diskCacheExecutor ),内存和硬盘缓存,默认的连接监听工厂(connectivityMonitorFactory ),Engine对象和RequestManagerRetriever 对象等等。
在使用的时候可以自定义这些配置,如果没有自定义就使用默认的。
有几个重要的对象创建,先看下它的构建内容:
RequestManagerRetriever
private final Handler handler;
private final RequestManagerFactory factory;
public RequestManagerRetriever(@Nullable RequestManagerFactory factory) {
this.factory = factory != null ? factory : DEFAULT_FACTORY;
handler = new Handler(Looper.getMainLooper(), this /* Callback */);
}
这个RequestManagerRetriever就上面with()方法中getRetriever(context)要获取的对象,它的构造方法创建了一个RequestManagerFactory工厂类,看名字就知道用于生成RequestManager的。
还新建了一个handler,用与发送消息切换线程的。
Engine对象:
public Engine(
MemoryCache memoryCache,
DiskCache.Factory diskCacheFactory,
GlideExecutor diskCacheExecutor,
GlideExecutor sourceExecutor,
GlideExecutor sourceUnlimitedExecutor,
GlideExecutor animationExecutor,
boolean isActiveResourceRetentionAllowed) {
this(
memoryCache,
diskCacheFactory,
diskCacheExecutor,
sourceExecutor,
sourceUnlimitedExecutor,
animationExecutor,
/*jobs=*/ null,
/*keyFactory=*/ null,
/*activeResources=*/ null,
/*engineJobFactory=*/ null,
/*decodeJobFactory=*/ null,
/*resourceRecycler=*/ null,
isActiveResourceRetentionAllowed);
}
Engine(MemoryCache cache,
DiskCache.Factory diskCacheFactory,
GlideExecutor diskCacheExecutor,
GlideExecutor sourceExecutor,
GlideExecutor sourceUnlimitedExecutor,
GlideExecutor animationExecutor,
Jobs jobs,
EngineKeyFactory keyFactory,
ActiveResources activeResources,
EngineJobFactory engineJobFactory,
DecodeJobFactory decodeJobFactory,
ResourceRecycler resourceRecycler,
boolean isActiveResourceRetentionAllowed) {
this.cache = cache;
this.diskCacheProvider = new LazyDiskCacheProvider(diskCacheFactory);
if (activeResources == null) {
activeResources = new ActiveResources(isActiveResourceRetentionAllowed);
}
this.activeResources = activeResources;
activeResources.setListener(this);
if (keyFactory == null) {
keyFactory = new EngineKeyFactory();
}
this.keyFactory = keyFactory;
if (jobs == null) {
jobs = new Jobs();
}
this.jobs = jobs;
if (engineJobFactory == null) {
engineJobFactory =
new EngineJobFactory(
diskCacheExecutor, sourceExecutor, sourceUnlimitedExecutor, animationExecutor, this);
}
this.engineJobFactory = engineJobFactory;
if (decodeJobFactory == null) {
decodeJobFactory = new DecodeJobFactory(diskCacheProvider);
}
this.decodeJobFactory = decodeJobFactory;
if (resourceRecycler == null) {
resourceRecycler = new ResourceRecycler();
}
this.resourceRecycler = resourceRecycler;
cache.setResourceRemovedListener(this);
}
Engine对象对传进来的参数进行了封装,并创建了几个工厂类EngineKeyFactory、engineJobFactory、decodeJobFactory以及几个HashMap类型的对象集合,如:jobs ,activeResources 等等。
回到build方法中,看到最后新建了一个Glide对象。看一下Glide的构造函数
Glide(
@NonNull Context context,
@NonNull Engine engine,
@NonNull MemoryCache memoryCache,
@NonNull BitmapPool bitmapPool,
@NonNull ArrayPool arrayPool,
@NonNull RequestManagerRetriever requestManagerRetriever,
@NonNull ConnectivityMonitorFactory connectivityMonitorFactory,
int logLevel,
@NonNull RequestOptions defaultRequestOptions,
@NonNull Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions,
@NonNull List<RequestListener<Object>> defaultRequestListeners,
boolean isLoggingRequestOriginsEnabled) {
this.engine = engine;
this.bitmapPool = bitmapPool;
this.arrayPool = arrayPool;
this.memoryCache = memoryCache;
this.requestManagerRetriever = requestManagerRetriever;
this.connectivityMonitorFactory = connectivityMonitorFactory;
//创建DecodeFormat解码格式,默认是PREFER_ARGB_8888
DecodeFormat decodeFormat = defaultRequestOptions.getOptions().get(Downsampler.DECODE_FORMAT);
bitmapPreFiller = new BitmapPreFiller(memoryCache, bitmapPool, decodeFormat);
final Resources resources = context.getResources();
//新建一个registry对象
registry = new Registry();
registry.register(new DefaultImageHeaderParser());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
registry.register(new ExifInterfaceImageHeaderParser());
}
......
//
registry.append()....register()...
//初始化ImageViewTargetFactory
ImageViewTargetFactory imageViewTargetFactory = new ImageViewTargetFactory();
//创建GlideContext对象
glideContext =
new GlideContext(
context,
arrayPool,
registry,
imageViewTargetFactory,
defaultRequestOptions,
defaultTransitionOptions,
defaultRequestListeners,
engine,
isLoggingRequestOriginsEnabled,
logLevel);
}
这个构造方法很长,上面将其简化,这里面创建了几个重要的对象
Registry
在Registry内部,提供了对如下几种类型模块的挂载支持:
/**
* 数据加载模块
*/
private final ModelLoaderRegistry modelLoaderRegistry;
/**
* 编码存储模块,提供将数据持久化存储到磁盘文件中的功能
*/
private final EncoderRegistry encoderRegistry;
/**
* 解码模块,能够将各种类型数据,例如文件、byte数组等数据解码成bitmap或者drawable等资源
*/
private final ResourceDecoderRegistry decoderRegistry;
/**
* 编码存储模块,提供将bitmap或者drawable等资源文件进行持久化存储的功能
*/
private final ResourceEncoderRegistry resourceEncoderRegistry;
/**
* 数据流重定向模块,例如重定向ByteBuffer中的position或者stream中的指针位置等
*/
private final DataRewinderRegistry dataRewinderRegistry;
/**
* 类型转换模块,提供将不同资源类型进行转换的能力,例如将bitmap转成drawable等
*/
private final TranscoderRegistry transcoderRegistry;
Registry主要是通过register和append方法添加很多的注册或解码转码方式等。
//
public <Data> Registry append(@NonNull Class<Data> dataClass, @NonNull Encoder<Data> encoder) {
encoderRegistry.append(dataClass, encoder);
return this;
}
public <Data, TResource> Registry append(
@NonNull String bucket,
@NonNull Class<Data> dataClass,
@NonNull Class<TResource> resourceClass,
@NonNull ResourceDecoder<Data, TResource> decoder) {
decoderRegistry.append(bucket, decoder, dataClass, resourceClass);
return this;
}
public <TResource> Registry append(
@NonNull Class<TResource> resourceClass, @NonNull ResourceEncoder<TResource> encoder) {
resourceEncoderRegistry.append(resourceClass, encoder);
return this;
}
public <Model, Data> Registry append(
@NonNull Class<Model> modelClass, @NonNull Class<Data> dataClass,
@NonNull ModelLoaderFactory<Model, Data> factory) {
modelLoaderRegistry.append(modelClass, dataClass, factory);
return this;
}
public Registry register(@NonNull DataRewinder.Factory<?> factory) {
dataRewinderRegistry.register(factory);
return this;
}
主要是存放到不同的对象中的集合变量中。这在后面用来解析是从内存,文件或是网络获取资源有着重要的作用。
GlideContext对象
GlideContext对象在后面也扮演中重要的角色,创建这个对象到目前为止只是为了初始化和赋值
public GlideContext(
@NonNull Context context,
@NonNull ArrayPool arrayPool,
@NonNull Registry registry,
@NonNull ImageViewTargetFactory imageViewTargetFactory,
@NonNull RequestOptions defaultRequestOptions,
@NonNull Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions,
@NonNull List<RequestListener<Object>> defaultRequestListeners,
@NonNull Engine engine,
boolean isLoggingRequestOriginsEnabled,
int logLevel) {
super(context.getApplicationContext());
this.arrayPool = arrayPool;
this.registry = registry;
this.imageViewTargetFactory = imageViewTargetFactory;
this.defaultRequestOptions = defaultRequestOptions;
this.defaultRequestListeners = defaultRequestListeners;
this.defaultTransitionOptions = defaultTransitionOptions;
this.engine = engine;
this.isLoggingRequestOriginsEnabled = isLoggingRequestOriginsEnabled;
this.logLevel = logLevel;
}
ImageViewTargetFactory
用来根据不同的Class构建target对象的.
这样Glide对象就创建完成了,回到getRetriever(@Nullable Context context)方法,返回了一个RequestManagerRetriever对象,这个对象就是build方法中创建的。
然后继续回到with()方法
public static RequestManager with(@NonNull Activity activity) {
return getRetriever(activity).get(activity);
}
由上面知道getRetriever(activity)方法返回的RequestManagerRetriever对象,进入它的get()方法看一下,如何生成RequestManager的
public RequestManager get(@NonNull Activity activity) {
//判断是否主线程
if (Util.isOnBackgroundThread()) {
//不是的话,就调用这个方法
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
android.app.FragmentManager fm = activity.getFragmentManager();
//
return fragmentGet(
activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
}
}
private RequestManager fragmentGet(@NonNull Context context,
@NonNull android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,
boolean isParentVisible) {
//RequestManagerFragment是一个Fragment
RequestManagerFragment current = getRequestManagerFragment(fm, parentHint, isParentVisible);
//获取RequestManager对象,第一次肯定等于null
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
Glide glide = Glide.get(context);
//创建requestManager
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
current.setRequestManager(requestManager);
}
return requestManager;
}
这个方法中的factory就是上面在创建RequestManagerRetriever对象的构造方法中的RequestManagerFactory工程类,调用它build方法创建requestManager
private RequestManagerFragment getRequestManagerFragment(
@NonNull final android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,
boolean isParentVisible) {
RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
current = pendingRequestManagerFragments.get(fm);
if (current == null) {
//新建了一个Fragment
current = new RequestManagerFragment();
current.setParentFragmentHint(parentHint);
if (isParentVisible) {
current.getGlideLifecycle().onStart();
}
pendingRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
这个方法新建了一个没有界面的Fragment,这样就将保证Glide与它依赖的Context的生命周期一致
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);
}
};
RequestManagerFactory工程类,调用它build方法新建一个RequestManager
这样with方法就解析完成,接下来看一下load方法
public RequestBuilder<Drawable> load(@Nullable String string) {
return asDrawable().load(string);
}
在调用with方法获取到RequestManager对象下,调用load方法,并传递我们的url参数。
看下asDrawable()的源码:
public RequestBuilder<Drawable> asDrawable() {
return as(Drawable.class);
}
public <ResourceType> RequestBuilder<ResourceType> as(
@NonNull Class<ResourceType> resourceClass) {
return new RequestBuilder<>(glide, this, resourceClass, context);
}
protected RequestBuilder(
@NonNull Glide glide,
RequestManager requestManager,
Class<TranscodeType> transcodeClass,
Context context) {
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());
}
asDrawable()创建了一个RequestBuilder对象,transcodeClass就是Drawable.class
然后又调用了RequestBuilder的load方法
public RequestBuilder<TranscodeType> load(@Nullable String string) {
return loadGeneric(string);
}
private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
this.model = model;
isModelSet = true;
return this;
}
可以看到load方法中什么也没有做,仅仅就是将URL放到model变量中,并设置isModelSet为true。
这样整个load方法就解析完了,返回了一个RequestBuilder对象,然后看一下into方法
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
Util.assertMainThread();
Preconditions.checkNotNull(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:
// Do nothing.
}
}
return into(
glideContext.buildImageViewTarget(view, transcodeClass),
/*targetListener=*/ null,
requestOptions,
Executors.mainThreadExecutor());
}
由上面的解析可以看出with以及load方法并没有进行真正的加载操作,所以可以知道into方法中会进行加载操作。接下来就一步一步深入去看一下。
into(ImageView view)方法有调用了另一个into的重载方法into(Y target,RequestListener targetListener,BaseRequestOptions<?> options,Executor callbackExecutor)
先看一下glideContext.buildImageViewTarget()方法:
public <X> ViewTarget<ImageView, X> buildImageViewTarget(
@NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {
return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
}
transcodeClass就是load方法时再as()方法中生成的Drawable.class
imageViewTargetFactory这个对象就是之前在创建Glide的构造方法中新建的ImageViewTargetFactory
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)");
}
}
从上面知道buildTarget方法中第二个参数是Drawable.class类型,所以新建DrawableImageViewTarget,并把view传递进去,
DrawableImageViewTarget继承于ImageViewTarget,又把view传递到了ViewTarget中,最终把view存放到了ViewTarget中的view变量中,并且还创建了一个SizeDeterminer对象:
public ViewTarget(@NonNull T view) {
this.view = Preconditions.checkNotNull(view);
sizeDeterminer = new SizeDeterminer(view);
}
这就是ImageView的最终去向,返回到RequestBuilder中,创建个DrawableImageViewTarget对象后,回到into方法中:
return into(
glideContext.buildImageViewTarget(view, transcodeClass),
/*targetListener=*/ null,
requestOptions,
Executors.mainThreadExecutor());
创建了一个Executors线程池:
public static Executor mainThreadExecutor() {
return MAIN_THREAD_EXECUTOR;
}
private static final Executor MAIN_THREAD_EXECUTOR = new Executor() {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override
public void execute(@NonNull Runnable command) {
handler.post(command);
}
};
在执行execute方法时就会调用handler.post方法将线程切换回主线程。接下来开始进入into的重载方法
private <Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener,
BaseRequestOptions<?> options,
Executor callbackExecutor) {
//检查target是否为null
Preconditions.checkNotNull(target);
//在load的时候设置为true
if (!isModelSet) {
throw new IllegalArgumentException("You must call #load() before calling #into()");
}
//构建Request对象
Request request = buildRequest(target, targetListener, options, callbackExecutor);
//获取target之前保存的Request对象
Request previous = target.getRequest();
//判断两个request是否一样
if (request.isEquivalentTo(previous)
&& !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
request.recycle();
// If the request is completed, beginning again will ensure the result is re-delivered,
// triggering RequestListeners and Targets. If the request is failed, beginning again will
// restart the request, giving it another chance to complete. If the request is already
// running, we can let it continue running without interruption.
if (!Preconditions.checkNotNull(previous).isRunning()) {
// Use the previous request rather than the new one to allow for optimizations like skipping
// setting placeholders, tracking and un-tracking Targets, and obtaining View dimensions
// that are done in the individual Request.
previous.begin();
}
return target;
}
requestManager.clear(target);
//给target设置request
target.setRequest(request);
//加载request
requestManager.track(target, request);
return target;
}
一步一步看看这个into中的方法,先获取Request,看一下如何获取的,进入buildRequest方法
private Request buildRequest(
Target<TranscodeType> target,
@Nullable RequestListener<TranscodeType> targetListener,
BaseRequestOptions<?> requestOptions,
Executor callbackExecutor) {
return buildRequestRecursive(
target,
targetListener,
/*parentCoordinator=*/ null,
transitionOptions,
requestOptions.getPriority(),
requestOptions.getOverrideWidth(),
requestOptions.getOverrideHeight(),
requestOptions,
callbackExecutor);
}
又调用了buildRequestRecursive方法
private Request buildRequestRecursive(
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(parentCoordinator);
parentCoordinator = errorRequestCoordinator;
}
Request mainRequest =
buildThumbnailRequestRecursive(
target,
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(
target,
targetListener,
errorRequestCoordinator,
errorBuilder.transitionOptions,
errorBuilder.getPriority(),
errorOverrideWidth,
errorOverrideHeight,
errorBuilder,
callbackExecutor);
errorRequestCoordinator.setRequests(mainRequest, errorRequest);
return errorRequestCoordinator;
}
调用buildThumbnailRequestRecursive方法生成Request对象
private Request buildThumbnailRequestRecursive(
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) {
// Recursive case: contains a potentially recursive thumbnail request builder.
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;
// Apply our transition by default to thumbnail requests but avoid overriding custom options
// that may have been applied on the thumbnail request explicitly.
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(parentCoordinator);
Request fullRequest =
obtainRequest(
target,
targetListener,
requestOptions,
coordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
callbackExecutor);
isThumbnailBuilt = true;
// Recursively generate thumbnail requests.
Request thumbRequest =
thumbnailBuilder.buildRequestRecursive(
target,
targetListener,
coordinator,
thumbTransitionOptions,
thumbPriority,
thumbOverrideWidth,
thumbOverrideHeight,
thumbnailBuilder,
callbackExecutor);
isThumbnailBuilt = false;
coordinator.setRequests(fullRequest, thumbRequest);
return coordinator;
} else if (thumbSizeMultiplier != null) {
// Base case: thumbnail multiplier generates a thumbnail request, but cannot recurse.
ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
Request fullRequest =
obtainRequest(
target,
targetListener,
requestOptions,
coordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
callbackExecutor);
BaseRequestOptions<?> thumbnailOptions =
requestOptions.clone().sizeMultiplier(thumbSizeMultiplier);
Request thumbnailRequest =
obtainRequest(
target,
targetListener,
thumbnailOptions,
coordinator,
transitionOptions,
getThumbnailPriority(priority),
overrideWidth,
overrideHeight,
callbackExecutor);
coordinator.setRequests(fullRequest, thumbnailRequest);
return coordinator;
} else {
// Base case: no thumbnail.
return obtainRequest(
target,
targetListener,
requestOptions,
parentCoordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
callbackExecutor);
}
}
这个方法前面都是一些缩略图的判断,直接跳过,进入最后一个else中看到又调用了obtainRequest方法
private Request obtainRequest(
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,
model,
transcodeClass,
requestOptions,
overrideWidth,
overrideHeight,
priority,
target,
targetListener,
requestListeners,
requestCoordinator,
glideContext.getEngine(),
transitionOptions.getTransitionFactory(),
callbackExecutor);
}
返回了一个SingleRequest对象,这样就可以知道需要的request是一个SingleRequest,进到obtain方法
public static <R> SingleRequest<R> obtain(
Context context,
GlideContext glideContext,
Object model,
Class<R> transcodeClass,
BaseRequestOptions<?> requestOptions,
int overrideWidth,
int overrideHeight,
Priority priority,
Target<R> target,
RequestListener<R> targetListener,
@Nullable List<RequestListener<R>> requestListeners,
RequestCoordinator requestCoordinator,
Engine engine,
TransitionFactory<? super R> animationFactory,
Executor callbackExecutor) {
@SuppressWarnings("unchecked") SingleRequest<R> request =
(SingleRequest<R>) POOL.acquire();
if (request == null) {
request = new SingleRequest<>();
}
request.init(
context,
glideContext,
model,
transcodeClass,
requestOptions,
overrideWidth,
overrideHeight,
priority,
target,
targetListener,
requestListeners,
requestCoordinator,
engine,
animationFactory,
callbackExecutor);
return request;
}
进行了一些初始化操作。新建了一个SingleRequest。这样调用buildRequest方法构建Request对象,是一个SingleRequest。回到into,继续看下一个target.getRequest();方法
由上面知道target是ImageViewTarget,又继承了ViewTarget,进入ViewTarget的getRequest方法看一下
public Request getRequest() {
Object tag = getTag();
Request request = null;
if (tag != null) {
if (tag instanceof Request) {
request = (Request) tag;
} else {
throw new IllegalArgumentException(
"You must not call setTag() on a view Glide is targeting");
}
}
return request;
}
private Object getTag() {
if (tagId == null) {
return view.getTag();
} else {
return view.getTag(tagId);
}
}
这里应该就比较熟悉了,这就是给request添加一个tag标记,防止图片显示错乱,由于是第一次加载,所以返回的是null。
target.getRequest();方法解析完了,继续into中的步骤,接下来就是
private <Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener,
BaseRequestOptions<?> options,
Executor callbackExecutor) {
......
//给target设置request
target.setRequest(request);
//加载request
requestManager.track(target, request);
......
}
target.setRequest(request);这个方法就不再详解,就是个request设置一个tag标记,主要看一下requestManager.track(target, request);
synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
targetTracker.track(target);
//加载request
requestTracker.runRequest(request);
}
requestTracker在新建requestManager的时候创建的new RequestTracker(),进入它的runRequest
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方法来企图开启请求,request其实就是SingleRequest对象,进入SingleRequest的begin方法
@Override
public synchronized void begin() {
assertNotCallingCallbacks();
stateVerifier.throwIfRecycled();
startTime = LogTime.getLogTime();
//判断model是否为空,model就是传进来的URL
if (model == null) {
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
width = overrideWidth;
height = overrideHeight;
}
int logLevel = getFallbackDrawable() == null ? Log.WARN : Log.DEBUG;
onLoadFailed(new GlideException("Received null model"), logLevel);
return;
}
//状态是否为running状态,默认是pending.Status是枚举类
if (status == Status.RUNNING) {
throw new IllegalArgumentException("Cannot restart a running request");
}
//是否状态为complete
if (status == Status.COMPLETE) {
onResourceReady(resource, DataSource.MEMORY_CACHE);
return;
}
//设置状态为waitong_for_size
status = Status.WAITING_FOR_SIZE;
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
onSizeReady(overrideWidth, overrideHeight);
} else {
target.getSize(this);
}
//根据Status对象状态和是否有占位图来设置加载过程中的占位图
if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)
&& canNotifyStatusChanged()) {
//设置占位图
target.onLoadStarted(getPlaceholderDrawable());
}
if (IS_VERBOSE_LOGGABLE) {
logV("finished run method in " + LogTime.getElapsedMillis(startTime));
}
}
Util.isValidDimensions判断图片的宽高,由于没有设置,直接进入onSizeReady方法
@Override
public synchronized void onSizeReady(int width, int height) {
stateVerifier.throwIfRecycled();
if (IS_VERBOSE_LOGGABLE) {
logV("Got onSizeReady in " + LogTime.getElapsedMillis(startTime));
}
if (status != Status.WAITING_FOR_SIZE) {
return;
}
//设置状态为running
status = Status.RUNNING;
float sizeMultiplier = requestOptions.getSizeMultiplier();
this.width = maybeApplySizeMultiplier(width, sizeMultiplier);
this.height = maybeApplySizeMultiplier(height, sizeMultiplier);
if (IS_VERBOSE_LOGGABLE) {
logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime));
}
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;
}
if (IS_VERBOSE_LOGGABLE) {
logV("finished onSizeReady in " + LogTime.getElapsedMillis(startTime));
}
}
onSizeReady方法中首先把State状态更改为RUNNING,然后获取到ImageView的宽高属性值,这个属性值就是要加载的图片的宽高。
Glide框架会根据请求加载图片的ImageView的宽高来进行加载相对应的宽高图片,每次根据view的大小加载的图片是不一定一样的。最后调用engine中的load方法
public synchronized <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;
//根据keyFactory构建key对象
EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations,
resourceClass, transcodeClass, options);
//获取内存缓存中的数据,弱引用
EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
if (active != null) {
cb.onResourceReady(active, DataSource.MEMORY_CACHE);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Loaded resource from active resources", startTime, key);
}
return null;
}
//获取内存缓存中的数据,LruCache
EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
if (cached != null) {
cb.onResourceReady(cached, DataSource.MEMORY_CACHE);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Loaded resource from cache", startTime, key);
}
return null;
}
EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
if (current != null) {
current.addCallback(cb, callbackExecutor);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Added to existing load", startTime, key);
}
return new LoadStatus(cb, current);
}
EngineJob<R> engineJob =
engineJobFactory.build(
key,
isMemoryCacheable,
useUnlimitedSourceExecutorPool,
useAnimationPool,
onlyRetrieveFromCache);
DecodeJob<R> decodeJob =
decodeJobFactory.build(
glideContext,
model,
key,
signature,
width,
height,
resourceClass,
transcodeClass,
priority,
diskCacheStrategy,
transformations,
isTransformationRequired,
isScaleOnlyOrNoTransform,
onlyRetrieveFromCache,
options,
engineJob);
jobs.put(key, engineJob);
engineJob.addCallback(cb, callbackExecutor);
engineJob.start(decodeJob);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Started new load", startTime, key);
}
return new LoadStatus(cb, engineJob);
}
所有重要的东西都在这里了:
<1> 通过keyFactory工厂来构建一个EngineKey对象,key关联着model,也就是url,它很根据model,view的宽高等等属性来构建一个EngineKey对象,这个对象可以用来指定缓存地址,可以用来从缓存中查找资源等。
<2> 根据创建的key对象分别调用loadFromCache和loadFromActiveResources方法来从内存中查找是否有缓存资源,如果有,则回调cb.onResourceReady来直接设置图片了。
<3> 使用engineJobFactory和decodeJobFactory构建EngineJob和DecodeJob对象,这两个对象是真正的加载资源的两个重要类。
EngineJob对象负责开启线程去加载资源,并且加载得资源后转换到主线程并进行回调;
DecodeJob是真正的执行者,它就是去网络加载资源的地方,EngineJob开启线程,真正执行的是DecodeJob
<4>engineJob.addCallback(cb, callbackExecutor);cb就是SingleRequest ,callbackExecutor就是into中创建的线程池用于切换到主线程
接下来主要看一下engineJob.start(decodeJob);方法
public synchronized void start(DecodeJob<R> decodeJob) {
this.decodeJob = decodeJob;
GlideExecutor executor = decodeJob.willDecodeFromCache()
? diskCacheExecutor
: getActiveSourceExecutor();
executor.execute(decodeJob);
}
调用了线程池GlideExecutor的execute方法,进入到decodeJob的run方法进行加载
public void run() {
GlideTrace.beginSectionFormat("DecodeJob#run(model=%s)", model);
DataFetcher<?> localFetcher = currentFetcher;
try {
if (isCancelled) {
notifyFailed();
return;
}
runWrapped();
} catch (CallbackException e) {
throw e;
} catch (Throwable t) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "DecodeJob threw unexpectedly"
+ ", isCancelled: " + isCancelled
+ ", stage: " + stage, t);
}
if (stage != Stage.ENCODE) {
throwables.add(t);
notifyFailed();
}
if (!isCancelled) {
throw t;
}
throw t;
} finally {
if (localFetcher != null) {
localFetcher.cleanup();
}
GlideTrace.endSection();
}
}
run方法中调用runWrapped方法,主要就是在它里面执行的,来看看它的源码:
private void runWrapped() {
switch (runReason) {
case INITIALIZE:
stage = getNextStage(Stage.INITIALIZE);
currentGenerator = getNextGenerator();
runGenerators();
break;
case SWITCH_TO_SOURCE_SERVICE:
runGenerators();
break;
case DECODE_DATA:
decodeFromRetrievedData();
break;
default:
throw new IllegalStateException("Unrecognized run reason: " + runReason);
}
}
在构造DecodeJob时调用init方法是runReason被赋值为INITIALIZE值,由此它将会进入到INITIALIZE分支中,调用getNextStage方法:
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是一个策略模式,就是设置的缓存策略,默认是AUTOMATIC,diskCacheStrategy.decodeCachedResource方法返回true。
因此getNextStage方法返回的是Stage.RESOURCE_CACHE,然后再回到runWrapped方法中,继续看getNextGenerator方法
private DataFetcherGenerator getNextGenerator() {
switch (stage) {
case RESOURCE_CACHE:
return new ResourceCacheGenerator(decodeHelper, this);
case DATA_CACHE:
return new DataCacheGenerator(decodeHelper, this);
case SOURCE:
return new SourceGenerator(decodeHelper, this);
case FINISHED:
return null;
default:
throw new IllegalStateException("Unrecognized stage: " + stage);
}
}
可以看到有三个加载器:
ResourceCacheGenerator 尝试从处理过的本地资源加载图片
DataCacheGenerator 尝试从未处理过的原始本地资源加载图片
SourceGenerator 尝试从远程加载图片
这里的getNextGenerator就返回一个ResourceCacheGenerator加载器,再次回到runWrapped方法,继续执行runGenerators方法
private void runGenerators() {
currentThread = Thread.currentThread();
startFetchTime = LogTime.getLogTime();
boolean isStarted = false;
//开始循环
while (!isCancelled && currentGenerator != null
&& !(isStarted = currentGenerator.startNext())) {
stage = getNextStage(stage);
currentGenerator = getNextGenerator();
if (stage == Stage.SOURCE) {
reschedule();
return;
}
}
if ((stage == Stage.FINISHED || isCancelled) && !isStarted) {
notifyFailed();
}
}
可以看到在while条件里调用了currentGenerator.startNext方法,这个currentGenerator就是上面的ResourceCacheGenerator记载器,进入它的startNext方法
public boolean startNext() {
//获取sourceIds
List<Key> sourceIds = helper.getCacheKeys();
if (sourceIds.isEmpty()) {
return false;
}
//获取资源类集合
List<Class<?>> resourceClasses = helper.getRegisteredResourceClasses();
if (resourceClasses.isEmpty()) {
if (File.class.equals(helper.getTranscodeClass())) {
return false;
}
throw new IllegalStateException(
"Failed to find any load path from " + helper.getModelClass() + " to "
+ helper.getTranscodeClass());
}
while (modelLoaders == null || !hasNextModelLoader()) {
resourceClassIndex++;
if (resourceClassIndex >= resourceClasses.size()) {
sourceIdIndex++;
if (sourceIdIndex >= sourceIds.size()) {
return false;
}
resourceClassIndex = 0;
}
Key sourceId = sourceIds.get(sourceIdIndex);
Class<?> resourceClass = resourceClasses.get(resourceClassIndex);
Transformation<?> transformation = helper.getTransformation(resourceClass);
currentKey = new ResourceCacheKey(
helper.getArrayPool(),
sourceId,
helper.getSignature(),
helper.getWidth(),
helper.getHeight(),
transformation,
resourceClass,
helper.getOptions());
cacheFile = helper.getDiskCache().get(currentKey);
if (cacheFile != null) {
sourceKey = sourceId;
modelLoaders = helper.getModelLoaders(cacheFile);
modelLoaderIndex = 0;
}
}
loadData = null;
boolean started = false;
while (!started && hasNextModelLoader()) {
ModelLoader<File, ?> modelLoader = modelLoaders.get(modelLoaderIndex++);
loadData = modelLoader.buildLoadData(cacheFile,
helper.getWidth(), helper.getHeight(), helper.getOptions());
if (loadData != null && helper.hasLoadPath(loadData.fetcher.getDataClass())) {
started = true;
loadData.fetcher.loadData(helper.getPriority(), this);
}
}
return started;
}
helper.getCacheKeys()方法
List<Key> getCacheKeys() {
if (!isCacheKeysSet) {
isCacheKeysSet = true;
cacheKeys.clear();
//获取LoadData集合
List<LoadData<?>> loadData = getLoadData();
//noinspection ForLoopReplaceableByForEach to improve perf
for (int i = 0, size = loadData.size(); i < size; i++) {
LoadData<?> data = loadData.get(i);
if (!cacheKeys.contains(data.sourceKey)) {
cacheKeys.add(data.sourceKey);
}
for (int j = 0; j < data.alternateKeys.size(); j++) {
if (!cacheKeys.contains(data.alternateKeys.get(j))) {
cacheKeys.add(data.alternateKeys.get(j));
}
}
}
}
return cacheKeys;
}
可以看到首先获取LoadData集合,然后会循环这个集合,然后将loadData的sourceKey等等添加到cacheKeys集合中并返回。
进入getLoadData方法。
List<LoadData<?>> getLoadData() {
if (!isLoadDataSet) {
isLoadDataSet = true;
loadData.clear();
//获取ModelLoader集合
List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model);
//noinspection ForLoopReplaceableByForEach to improve perf
for (int i = 0, size = modelLoaders.size(); i < size; i++) {
ModelLoader<Object, ?> modelLoader = modelLoaders.get(i);
//调用modelLoader.buildLoadData得到LoadData对象
LoadData<?> current =
modelLoader.buildLoadData(model, width, height, options);
if (current != null) {
loadData.add(current);
}
}
}
return loadData;
}
首先获取了一个ModelLoader集合。这个ModelLoader是什么东西,再进入glideContext.getRegistry().getModelLoaders去看一下
public <Model> List<ModelLoader<Model, ?>> getModelLoaders(@NonNull Model model) {
List<ModelLoader<Model, ?>> result = modelLoaderRegistry.getModelLoaders(model);
if (result.isEmpty()) {
throw new NoModelLoaderAvailableException(model);
}
return result;
}
这个方法只是做了一个非空判断,进入modelLoaderRegistry.getModelLoaders方法
public <A> List<ModelLoader<A, ?>> getModelLoaders(@NonNull A model) {
List<ModelLoader<A, ?>> modelLoaders = getModelLoadersForClass(getClass(model));
int size = modelLoaders.size();
boolean isEmpty = true;
List<ModelLoader<A, ?>> filteredLoaders = Collections.emptyList();
//noinspection ForLoopReplaceableByForEach to improve perf
for (int i = 0; i < size; i++) {
ModelLoader<A, ?> loader = modelLoaders.get(i);
if (loader.handles(model)) {
if (isEmpty) {
filteredLoaders = new ArrayList<>(size - i);
isEmpty = false;
}
filteredLoaders.add(loader);
}
}
return filteredLoaders;
}
这个方法还是没有获取到ModelLoader,再进入getModelLoadersForClass方法
private synchronized <A> List<ModelLoader<A, ?>> getModelLoadersForClass(
@NonNull Class<A> modelClass) {
//从缓存获取ModelLoader
List<ModelLoader<A, ?>> loaders = cache.get(modelClass);
if (loaders == null) {
//没有就去获取
loaders = Collections.unmodifiableList(multiModelLoaderFactory.build(modelClass));
//将ModelLoader放到缓存中
cache.put(modelClass, loaders);
}
return loaders;
}
先从缓存中获取ModelLoader,如果没有,就调用multiModelLoaderFactory.build方法去获取,这样就知道是在build这个方法中获取的,进去看一下
synchronized <Model> List<ModelLoader<Model, ?>> build(@NonNull Class<Model> modelClass) {
try {
List<ModelLoader<Model, ?>> loaders = new ArrayList<>();
for (Entry<?, ?> entry : entries) {
if (alreadyUsedEntries.contains(entry)) {
continue;
}
if (entry.handles(modelClass)) {
alreadyUsedEntries.add(entry);
loaders.add(this.<Model, Object>build(entry));
alreadyUsedEntries.remove(entry);
}
}
return loaders;
} catch (Throwable t) {
alreadyUsedEntries.clear();
throw t;
}
}
这个方法里面终于是获取到了ModelLoader,看一下是如何获取的。
首先是去循环这个Entry集合,在集合里面调用entry.handles去拿到对应的ModelLoader,最后返回。
这里又出来一个Entry,这又是什么东西,在multiModelLoaderFactory类中找一下,可以看到这个集合是一个list集合,看一下是在什么地方添加元素的。
private <Model, Data> void add(
@NonNull Class<Model> modelClass,
@NonNull Class<Data> dataClass,
@NonNull ModelLoaderFactory<? extends Model, ? extends Data> factory,
boolean append) {
Entry<Model, Data> entry = new Entry<>(modelClass, dataClass, factory);
entries.add(append ? entries.size() : 0, entry);
}
是在multiModelLoaderFactory类add方法里面添加元素的,再往上找看这个add是在什么地方调用的。
synchronized <Model, Data> void append(
@NonNull Class<Model> modelClass,
@NonNull Class<Data> dataClass,
@NonNull ModelLoaderFactory<? extends Model, ? extends Data> factory) {
add(modelClass, dataClass, factory, /*append=*/ true);
}
在append方法找到调用add方法,还是没有找到根,再往上找。看看append方法是谁调用的。
public synchronized <Model, Data> void append(
@NonNull Class<Model> modelClass,
@NonNull Class<Data> dataClass,
@NonNull ModelLoaderFactory<? extends Model, ? extends Data> factory) {
multiModelLoaderFactory.append(modelClass, dataClass, factory);
cache.clear();
}
在ModelLoaderRegistry类中的append看到了multiModelLoaderFactory.append方法的调用。
这个ModelLoaderRegistry类就熟悉了,就是在上面初始化Registry类的时候创建的,是数据加载模块,这样的话就应该能猜到它的append方法应该就是在Registry类中调用了。
public <Model, Data> Registry append(
@NonNull Class<Model> modelClass, @NonNull Class<Data> dataClass,
@NonNull ModelLoaderFactory<Model, Data> factory) {
modelLoaderRegistry.append(modelClass, dataClass, factory);
return this;
}
这个Registry.append不就是在初始化Glide时候添加的一些数据吗?由于初始化Glide的方法比较多,所以上面就没有列出来,接下来看一下就添加了写什么:
数据加载模块(modelLoaderRegistry)
append(
@NonNull Class<Model> modelClass, @NonNull Class<Data> dataClass,
@NonNull ModelLoaderFactory<Model, Data> factory)
append(Bitmap.class, Bitmap.class, UnitModelLoader.Factory.<Bitmap>getInstance())
append(GifDecoder.class, GifDecoder.class, UnitModelLoader.Factory.<GifDecoder>getInstance())
append(File.class, ByteBuffer.class, new ByteBufferFileLoader.Factory())
append(File.class, InputStream.class, new FileLoader.StreamFactory())
append(File.class, ParcelFileDescriptor.class, new FileLoader.FileDescriptorFactory())
append(File.class, File.class, UnitModelLoader.Factory.<File>getInstance())
append(int.class, InputStream.class, resourceLoaderStreamFactory)
append(int.class,ParcelFileDescriptor.class,resourceLoaderFileDescriptorFactory)
append(int.class, Uri.class, resourceLoaderUriFactory)
append(int.class,AssetFileDescriptor.class,resourceLoaderAssetFileDescriptorFactory)
append(Integer.class, InputStream.class, resourceLoaderStreamFactory)
append(Integer.class,ParcelFileDescriptor.class,resourceLoaderFileDescriptorFactory)
append(Integer.class, Uri.class, resourceLoaderUriFactory)
append(Integer.class,AssetFileDescriptor.class,resourceLoaderAssetFileDescriptorFactory)
append(String.class, InputStream.class, new StringLoader.StreamFactory())
append(String.class, ParcelFileDescriptor.class, new StringLoader.FileDescriptorFactory())
append(String.class, AssetFileDescriptor.class, new StringLoader.AssetFileDescriptorFactory())
append(String.class, InputStream.class, new DataUrlLoader.StreamFactory<String>())
append(Uri.class, InputStream.class, new DataUrlLoader.StreamFactory<Uri>())
append(Uri.class, InputStream.class, new HttpUriLoader.Factory())
append(Uri.class, InputStream.class, new AssetUriLoader.StreamFactory(context.getAssets()))
append(Uri.class, InputStream.class, new MediaStoreImageThumbLoader.Factory(context))
append(Uri.class, InputStream.class, new MediaStoreVideoThumbLoader.Factory(context))
append(Uri.class,InputStream.class,new UriLoader.StreamFactory(contentResolver))
append(Uri.class,ParcelFileDescriptor.class,new AssetUriLoader.FileDescriptorFactory(context.getAssets()))
append(Uri.class,ParcelFileDescriptor.class,new UriLoader.FileDescriptorFactory(contentResolver))
append(Uri.class,AssetFileDescriptor.class,new UriLoader.AssetFileDescriptorFactory(contentResolver))
append(Uri.class, InputStream.class, new UrlUriLoader.StreamFactory())
append(Uri.class, File.class, new MediaStoreFileLoader.Factory(context))
append(Uri.class, Uri.class, UnitModelLoader.Factory.<Uri>getInstance())
append(URL.class, InputStream.class, new UrlLoader.StreamFactory())
append(GlideUrl.class, InputStream.class, new HttpGlideUrlLoader.Factory())
append(byte[].class, ByteBuffer.class, new ByteArrayLoader.ByteBufferFactory())
append(byte[].class, InputStream.class, new ByteArrayLoader.StreamFactory())
append(Drawable.class, Drawable.class, UnitModelLoader.Factory.<Drawable>getInstance())
编码存储模块,提供将数据持久化存储到磁盘文件中的功能(EncoderRegistry )
append(ByteBuffer.class, new ByteBufferEncoder())
append(InputStream.class, new StreamEncoder(arrayPool))
解码模块,能够将各种类型数据,例如文件、byte数组等数据解码成bitmap或者drawable等资源(ResourceDecoderRegistry)
append(Registry.BUCKET_BITMAP, ByteBuffer.class, Bitmap.class, byteBufferBitmapDecoder)
append(Registry.BUCKET_GIF, ByteBuffer.class, GifDrawable.class, byteBufferGifDecoder)
append(Registry.BUCKET_BITMAP_DRAWABLE,ByteBuffer.class,BitmapDrawable.class,new BitmapDrawableDecoder<>(resources, byteBufferBitmapDecoder))
append(Registry.BUCKET_GIF,InputStream.class,GifDrawable.class,new StreamGifDecoder(imageHeaderParsers, byteBufferGifDecoder, arrayPool))
append(Registry.BUCKET_BITMAP_DRAWABLE,InputStream.class,BitmapDrawable.class,new BitmapDrawableDecoder<>(resources, streamBitmapDecoder))
append(Registry.BUCKET_BITMAP, InputStream.class, Bitmap.class, streamBitmapDecoder)
append(Registry.BUCKET_BITMAP_DRAWABLE,ParcelFileDescriptor.class,BitmapDrawable.class,new BitmapDrawableDecoder<>(resources, parcelFileDescriptorVideoDecoder))
append(Registry.BUCKET_BITMAP,ParcelFileDescriptor.class,Bitmap.class,parcelFileDescriptorVideoDecoder)
append(Registry.BUCKET_BITMAP,AssetFileDescriptor.class,Bitmap.class,VideoDecoder.asset(bitmapPool))
append(Registry.BUCKET_BITMAP, Bitmap.class, Bitmap.class, new UnitBitmapDecoder())
append(Registry.BUCKET_BITMAP,GifDecoder.class,Bitmap.class,new GifFrameResourceDecoder(bitmapPool))
BUCKET_APPEND_ALL
append(Uri.class, Drawable.class, resourceDrawableDecoder)
append(Uri.class, Bitmap.class, new ResourceBitmapDecoder(resourceDrawableDecoder, bitmapPool))
append(File.class, File.class, new FileDecoder())
append(Drawable.class, Drawable.class, new UnitDrawableDecoder())
编码存储模块,提供将bitmap或者drawable等资源文件进行持久化存储的功能(ResourceEncoderRegistry)
append(Bitmap.class, bitmapEncoder)
append(BitmapDrawable.class, new BitmapDrawableEncoder(bitmapPool, bitmapEncoder))
append(GifDrawable.class, new GifDrawableEncoder())
数据流重定向模块,例如重定向ByteBuffer中的position或者stream中的指针位置等(DataRewinderRegistry)
register(@NonNull DataRewinder.Factory<?> factory)
register(new ByteBufferRewinder.Factory())
register(new InputStreamRewinder.Factory(arrayPool))
类型转换模块,提供将不同资源类型进行转换的能力,例如将bitmap转成drawable等(TranscoderRegistry)
register(
@NonNull Class<TResource> resourceClass, @NonNull Class<Transcode> transcodeClass,
@NonNull ResourceTranscoder<TResource, Transcode> transcoder)
register(Bitmap.class,BitmapDrawable.class,new BitmapDrawableTranscoder(resources))
register(Bitmap.class, byte[].class, bitmapBytesTranscoder)
register(Drawable.class,byte[].class,new DrawableBytesTranscoder(bitmapPool, bitmapBytesTranscoder, gifDrawableBytesTranscoder))
register(GifDrawable.class, byte[].class, gifDrawableBytesTranscoder);
了解了这些之后再回到multiModelLoaderFactory.build方法中,这下就知道了Entry集合放的就是数据加载模块中的内容,然后调用entry.handles去匹配。
public boolean handles(@NonNull Class<?> modelClass) {
return this.modelClass.isAssignableFrom(modelClass);
}
这个方法就是handles方法传进来的参数(String.Class)是否entry中的变量modelClass的子类,去数据加载模块中看一下有没有String.Class对应。找到下面四个:
append(String.class, InputStream.class, new StringLoader.StreamFactory())
append(String.class, ParcelFileDescriptor.class, new StringLoader.FileDescriptorFactory())
append(String.class, AssetFileDescriptor.class, new StringLoader.AssetFileDescriptorFactory())
append(String.class, InputStream.class, new DataUrlLoader.StreamFactory<String>())
然后调用了这些ModelLoader的ModelLoaderFactory的build方法,这是一个工厂模式。通过build方法返回ModelLoader。就以StringLoader.StreamFactory()为例看一下:
public static class StreamFactory implements ModelLoaderFactory<String, InputStream> {
@NonNull
@Override
public ModelLoader<String, InputStream> build(
@NonNull MultiModelLoaderFactory multiFactory) {
return new StringLoader<>(multiFactory.build(Uri.class, InputStream.class));
}
@Override
public void teardown() {
// Do nothing.
}
}
可以看到build中又调用了multiFactory.build的方法,并传递了两个参数(Uri.class, InputStream.class)。进入看一下:
public synchronized <Model, Data> ModelLoader<Model, Data> build(@NonNull Class<Model> modelClass,
@NonNull Class<Data> dataClass) {
try {
List<ModelLoader<Model, Data>> loaders = new ArrayList<>();
boolean ignoredAnyEntries = false;
for (Entry<?, ?> entry : entries) {
if (alreadyUsedEntries.contains(entry)) {
ignoredAnyEntries = true;
continue;
}
if (entry.handles(modelClass, dataClass)) {
alreadyUsedEntries.add(entry);
loaders.add(this.<Model, Data>build(entry));
alreadyUsedEntries.remove(entry);
}
}
if (loaders.size() > 1) {
return factory.build(loaders, throwableListPool);
} else if (loaders.size() == 1) {
return loaders.get(0);
} else {
if (ignoredAnyEntries) {
return emptyModelLoader();
} else {
throw new NoModelLoaderAvailableException(modelClass, dataClass);
}
}
} catch (Throwable t) {
alreadyUsedEntries.clear();
throw t;
}
}
可以看到再次查找数据加载模块中的内容,找到为(Uri.class, InputStream.class)匹配的factory,如果找到了就并再次调用factory.build
append(Uri.class, InputStream.class, new DataUrlLoader.StreamFactory<Uri>())
append(Uri.class, InputStream.class, new HttpUriLoader.Factory())
append(Uri.class, InputStream.class, new AssetUriLoader.StreamFactory(context.getAssets()))
append(Uri.class, InputStream.class, new MediaStoreImageThumbLoader.Factory(context))
append(Uri.class, InputStream.class, new MediaStoreVideoThumbLoader.Factory(context))
append(Uri.class,InputStream.class,new UriLoader.StreamFactory(contentResolver))
找到这几个,以HttpUriLoader为例进入看一下:
public static class Factory implements ModelLoaderFactory<Uri, InputStream> {
@NonNull
@Override
public ModelLoader<Uri, InputStream> build(MultiModelLoaderFactory multiFactory) {
return new HttpUriLoader(multiFactory.build(GlideUrl.class, InputStream.class));
}
@Override
public void teardown() {
// Do nothing.
}
}
这里又调用了multiFactory.build方法,又传进了两个参数(GlideUrl.class, InputStream.class),同理在数据加载模块中找一下:
append(GlideUrl.class, InputStream.class, new HttpGlideUrlLoader.Factory())
进到HttpGlideUrlLoader类中看一下:
public static class Factory implements ModelLoaderFactory<GlideUrl, InputStream> {
private final ModelCache<GlideUrl, GlideUrl> modelCache = new ModelCache<>(500);
@NonNull
@Override
public ModelLoader<GlideUrl, InputStream> build(MultiModelLoaderFactory multiFactory) {
return new HttpGlideUrlLoader(modelCache);
}
@Override
public void teardown() {
// Do nothing.
}
}
在build中可以看到最终创建了一个HttpGlideUrlLoader对象。以此类推这一次就创建了三个对象StringLoader、HttpUriLoader、HttpGlideUrlLoader。
其他的ModelLoader对象也是如此创建的。就不一一例举了。
找到对应的ModelLoader集合,就返回到modelLoaderRegistry.getModelLoaders方法,这个方法可以看到循环了ModelLoader集合,然后调用了ModelLoader的handles方法,再次过滤。
进入到每个ModelLoader看一下,这就以上面创建好的StringLoader为例:
public class StringLoader<Data> implements ModelLoader<String, Data> {
......
@Override
public boolean handles(@NonNull String model) {
return true;
}
......
}
可以看到返回的是true。这就拿到了再次过滤后的ModelLoader。返回到modelLoaderRegistry.getModelLoaders方法,将过滤后的modelLoader集合返回。再次回到了getLoadData()方法中,这个方法遍历所有的ModelLoader,然后调用了ModelLoader.buildLoadData()方法,还是以StringLoader为例:
@Override
public LoadData<Data> buildLoadData(@NonNull String model, int width, int height,@NonNull Options options) {
//将String解析成Uri
Uri uri = parseUri(model);
if (uri == null || !uriLoader.handles(uri)) {
return null;
}
return uriLoader.buildLoadData(uri, width, height, options);
}
看到又调用了HttpUriLoader的buildLoadData方法。
@Override
public LoadData<InputStream> buildLoadData(@NonNull Uri model, int width, int height,@NonNull Options options) {
return urlLoader.buildLoadData(new GlideUrl(model.toString()), width, height, options);
}
又调用了HttpGlideUrlLoader中的buildLoadData方法
public LoadData<InputStream> buildLoadData(@NonNull GlideUrl model, int width, int height,
@NonNull Options options) {
//将model转为GlideUrl对象
GlideUrl url = model;
if (modelCache != null) {
url = modelCache.get(model, 0, 0);
if (url == null) {
modelCache.put(model, 0, 0, model);
url = model;
}
}
int timeout = options.get(TIMEOUT);
return new LoadData<>(url, new HttpUrlFetcher(url, timeout));
}
可以看到最后创建了一个LoadData对象,并且创建了一个HttpUrlFetcher对象,并将LoadData对象返回。
再次回到了getLoadData()方法中往下看,最终是将获取的LoadData对象返回给了getCacheKeys()方法,至此getCacheKeys()方法就解析完了。
继续helper.getRegisteredResourceClasses()方法
List<Class<?>> getRegisteredResourceClasses() {
return glideContext.getRegistry().getRegisteredResourceClasses(model.getClass(), resourceClass, transcodeClass);
}
public <Model, TResource, Transcode> List<Class<?>> getRegisteredResourceClasses(
@NonNull Class<Model> modelClass,
@NonNull Class<TResource> resourceClass,
@NonNull Class<Transcode> transcodeClass) {
//从缓存中获取
List<Class<?>> result =
modelToResourceClassCache.get(modelClass, resourceClass, transcodeClass);
if (result == null) {
result = new ArrayList<>();
//通过匹配modelClass获取dataClass
List<Class<?>> dataClasses = modelLoaderRegistry.getDataClasses(modelClass);
//循环dataClass
for (Class<?> dataClass : dataClasses) {
//通过匹配dataClass, resourceClass获取registeredResourceClasses
List<? extends Class<?>> registeredResourceClasses =
decoderRegistry.getResourceClasses(dataClass, resourceClass);
//循环registeredResourceClasses
for (Class<?> registeredResourceClass : registeredResourceClasses) {
//通过匹配registeredResourceClass, transcodeClass获取registeredTranscodeClasses
List<Class<Transcode>> registeredTranscodeClasses = transcoderRegistry
.getTranscodeClasses(registeredResourceClass, transcodeClass);
if (!registeredTranscodeClasses.isEmpty() && !result.contains(registeredResourceClass)) {
//将得到的registeredResourceClass添加到集合中
result.add(registeredResourceClass);
}
}
}
//添加到缓存中
modelToResourceClassCache.put(
modelClass, resourceClass, transcodeClass, Collections.unmodifiableList(result));
}
return result;
}
经过上面获取ModelLoader的分析,看到这个getRegisteredResourceClasses方法就应该比较熟悉了。
从缓存中获取RegisteredResourceClasses,没有的话首先通过匹配modelClass获取dataClass,进到modelLoaderRegistry.getDataClasses方法
public synchronized List<Class<?>> getDataClasses(@NonNull Class<?> modelClass) {
return multiModelLoaderFactory.getDataClasses(modelClass);
}
synchronized List<Class<?>> getDataClasses(@NonNull Class<?> modelClass) {
List<Class<?>> result = new ArrayList<>();
for (Entry<?, ?> entry : entries) {
if (!result.contains(entry.dataClass) && entry.handles(modelClass)) {
result.add(entry.dataClass);
}
}
return result;
}
在ModelLoader的分析中,知道这就是从数据加载模块中匹配DataClasses,去数据加载模块看一下:
append(String.class, InputStream.class, new StringLoader.StreamFactory())
append(String.class, ParcelFileDescriptor.class, new StringLoader.FileDescriptorFactory())
append(String.class, AssetFileDescriptor.class, new StringLoader.AssetFileDescriptorFactory())
append(String.class, InputStream.class, new DataUrlLoader.StreamFactory<String>())
匹配到之后,拿到其中的dataClass,也就是append方法中的第二个参数,比如InputStream.class等等。然后将获取的DataClasses返回。再回到getRegisteredResourceClasses方法中,继续执行。通过匹配的dataClass, resourceClass获取registeredResourceClasses,进到decoderRegistry.getResourceClasses方法中
public synchronized <T, R> List<Class<R>> getResourceClasses(@NonNull Class<T> dataClass,
@NonNull Class<R> resourceClass) {
List<Class<R>> result = new ArrayList<>();
for (String bucket : bucketPriorityList) {
List<Entry<?, ?>> entries = decoders.get(bucket);
if (entries == null) {
continue;
}
//循环所有的解码封装类
for (Entry<?, ?> entry : entries) {
//过滤
if (entry.handles(dataClass, resourceClass)
&& !result.contains((Class<R>) entry.resourceClass)) {
result.add((Class<R>) entry.resourceClass);
}
}
}
return result;
}
这个方法又是从解码模块中去匹配需要的ResourceClasses,去解码模块看一下:
append(Registry.BUCKET_GIF,InputStream.class,GifDrawable.class,new StreamGifDecoder(imageHeaderParsers, byteBufferGifDecoder, arrayPool))
append(Registry.BUCKET_BITMAP_DRAWABLE,InputStream.class,BitmapDrawable.class,new BitmapDrawableDecoder<>(resources, streamBitmapDecoder))
append(Registry.BUCKET_BITMAP, InputStream.class, Bitmap.class, streamBitmapDecoder)
append(Registry.BUCKET_BITMAP_DRAWABLE,ParcelFileDescriptor.class,BitmapDrawable.class,new BitmapDrawableDecoder<>(resources, parcelFileDescriptorVideoDecoder))
append(Registry.BUCKET_BITMAP,ParcelFileDescriptor.class,Bitmap.class,parcelFileDescriptorVideoDecoder)
append(Registry.BUCKET_BITMAP,AssetFileDescriptor.class,Bitmap.class,VideoDecoder.asset(bitmapPool))
匹配到了之后,拿到ResourceClasse就是append方法中的第三个参数,比如 GifDrawable ,最后返回。
再次回到getRegisteredResourceClasses方法中,继续执行。去匹配registeredTranscodeClasses。进到transcoderRegistry.getTranscodeClasses()方法中看一下:
public synchronized <Z, R> List<Class<R>> getTranscodeClasses(
@NonNull Class<Z> resourceClass, @NonNull Class<R> transcodeClass) {
List<Class<R>> transcodeClasses = new ArrayList<>();
// GifDrawable -> Drawable is just the UnitTranscoder, as is GifDrawable -> GifDrawable.
if (transcodeClass.isAssignableFrom(resourceClass)) {
transcodeClasses.add(transcodeClass);
return transcodeClasses;
}
for (Entry<?, ?> entry : transcoders) {
if (entry.handles(resourceClass, transcodeClass)) {
transcodeClasses.add(transcodeClass);
}
}
return transcodeClasses;
}
这个方法分为两部分:
一部分就是如果resourceClass是transcodeClass的子类,比如GifDrawable和BitmapDrawable就是Drawable的子类,就将Drawable类型添加到集合中直接返回。
另一部分如果不是Drawable的子类,比如Bitmap,那么就需要从数据类型转换中匹配。去数据类型转换模块中看一下:
register(Bitmap.class,BitmapDrawable.class,new BitmapDrawableTranscoder(resources))
匹配到之后,再将Drawable类型添加到集合中返回。
再次回到getRegisteredResourceClasses方法中,继续执行。如果返回的registeredTranscodeClasses不为空,就将匹配到的RegisteredResourceClasses添加到集合并添加到缓存中,最后返回。这样getRegisteredResourceClasses方法就执行完成了,然后回到ResourceCacheGenerator.startNext方法中,继续往下看。
进到while循环里面,创建了一个ResourceCacheKey对象,然后根据key从硬盘缓存中获取缓存数据,由于是第一次,没有缓存,所以ResourceCacheGenerator.startNext方法最终就会返回false。然后就会回到DecodeJob的runGenerators()方法中,然后就会进入到while的循环体中,又会执行stage = getNextStage(stage);currentGenerator = getNextGenerator();这两个方法,这次拿到的就是DataCacheGenerator加载器中,第一次去加载图片的时候是没有缓存的,所以DataCacheGenerator也是拿不到数据的,这个就不详细分析了。之后就会拿到SourceGenerator加载器,去远程加载图片资源。转到SourceGenerator加载器还有一些小细节,就不深究了,接下来主要看一下是如何远程加载图片资源的。进入SourceGenerator.startNext()
public boolean startNext() {
if (dataToCache != null) {
Object data = dataToCache;
dataToCache = null;
cacheData(data);
}
if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {
return true;
}
sourceCacheGenerator = null;
loadData = null;
boolean started = false;
while (!started && hasNextModelLoader()) {
loadData = helper.getLoadData().get(loadDataListIndex++);
if (loadData != null
&& (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
|| helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
started = true;
loadData.fetcher.loadData(helper.getPriority(), this);
}
}
return started;
}
private boolean hasNextModelLoader() {
return loadDataListIndex < helper.getLoadData().size();
}
还没有获取到数据,所以前两个判断跳过,直接进入到while条件中,看hasNextModelLoader(),这个方法中调用了helper.getLoadData()方法
这个getLoadData()方法就是上面分析获取ModelLoader,最终就获取到了一个
new LoadData<>(url, new HttpUrlFetcher(url, timeout));
回到SourceGenerator.startNext()进入到while循环里面,这里面有个判断
helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
经过上面的分析知道默认的缓存策略是AUTOMATIC,它的isDataCacheable:
public boolean isDataCacheable(DataSource dataSource) {
return dataSource == DataSource.REMOTE;
}
看一下loadData.fetcher.getDataSource()方法,也就是HttpUrlFetcher.getDataSource方法
public DataSource getDataSource() {
return DataSource.REMOTE;
}
可以看到这个判断是是相等的,所以进入到判断里面。调用了loadData.fetcher.loadData方法
@Override
public void loadData(@NonNull Priority priority,
@NonNull DataCallback<? super InputStream> callback) {
long startTime = LogTime.getLogTime();
try {
InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
callback.onDataReady(result);
} catch (IOException e) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Failed to load data for url", e);
}
callback.onLoadFailed(e);
} finally {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Finished http url fetcher fetch in " + LogTime.getElapsedMillis(startTime));
}
}
}
private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl,
Map<String, String> headers) throws IOException {
if (redirects >= MAXIMUM_REDIRECTS) {
throw new HttpException("Too many (> " + MAXIMUM_REDIRECTS + ") redirects!");
} else {
try {
if (lastUrl != null && url.toURI().equals(lastUrl.toURI())) {
throw new HttpException("In re-direct loop");
}
} catch (URISyntaxException e) {
// Do nothing, this is best effort.
}
}
urlConnection = connectionFactory.build(url);
for (Map.Entry<String, String> headerEntry : headers.entrySet()) {
urlConnection.addRequestProperty(headerEntry.getKey(), headerEntry.getValue());
}
urlConnection.setConnectTimeout(timeout);
urlConnection.setReadTimeout(timeout);
urlConnection.setUseCaches(false);
urlConnection.setDoInput(true);
urlConnection.setInstanceFollowRedirects(false);
urlConnection.connect();
stream = urlConnection.getInputStream();
if (isCancelled) {
return null;
}
final int statusCode = urlConnection.getResponseCode();
if (isHttpOk(statusCode)) {
return getStreamForSuccessfulRequest(urlConnection);
} else if (isHttpRedirect(statusCode)) {
String redirectUrlString = urlConnection.getHeaderField("Location");
if (TextUtils.isEmpty(redirectUrlString)) {
throw new HttpException("Received empty or null redirect url");
}
URL redirectUrl = new URL(url, redirectUrlString);
cleanup();
return loadDataWithRedirects(redirectUrl, redirects + 1, url, headers);
} else if (statusCode == INVALID_STATUS_CODE) {
throw new HttpException(statusCode);
} else {
throw new HttpException(urlConnection.getResponseMessage(), statusCode);
}
}
这里就看到了熟悉的HttpURLConnection,就不再进行过多的解析了,这里面有一个重定向的判断isHttpRedirect(statusCode),
private static boolean isHttpRedirect(int statusCode) {
return statusCode / 100 == 3;
}
如果返回码是3xx重定向时,就会获取到重定向的redirectUrlString,重新加载。最大重定向次数MAXIMUM_REDIRECTS是5次。
拿到InputStream流对象之后,调用callback.onDataReady(result);回调给SourceGenerator。
这样SourceGenerator.startNext()方法就分析完了,就会调用callback.onDataReady(result);进入回调方法SourceGenerator.onDataReady看一下,
public void onDataReady(Object data) {
DiskCacheStrategy diskCacheStrategy = helper.getDiskCacheStrategy();
if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) {
dataToCache = data;
cb.reschedule();
} else {
cb.onDataFetcherReady(loadData.sourceKey, data, loadData.fetcher,
loadData.fetcher.getDataSource(), originalKey);
}
}
默认是缓存的,所以会进入if判断中,去执行缓存操作,这里就不再进行详细的分析,经过缓存操作之后data就变成了DirectByteBuffer类型。
最终还是会调用cb.onDataFetcherReady(),这里主要关注一下Glide是如何将流对象解码和转码的。
直接进到cb.onDataFetcherReady(),也就是DecodeJob的onDataFetcherReady方法看一下:
public void onDataFetcherReady(Key sourceKey, Object data, DataFetcher<?> fetcher,
DataSource dataSource, Key attemptedKey) {
this.currentSourceKey = sourceKey;
this.currentData = data;
this.currentFetcher = fetcher;
this.currentDataSource = dataSource;
this.currentAttemptingKey = attemptedKey;
if (Thread.currentThread() != currentThread) {
runReason = RunReason.DECODE_DATA;
callback.reschedule(this);
} else {
GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData");
try {
decodeFromRetrievedData();
} finally {
GlideTrace.endSection();
}
}
}
判断是否在同一线程,还没有进行线程切换,还是在子线程,所以跳过进入else中。然后调用 decodeFromRetrievedData 方法来解码数据:
private void decodeFromRetrievedData() {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Retrieved data", startFetchTime,
"data: " + currentData
+ ", cache key: " + currentSourceKey
+ ", fetcher: " + currentFetcher);
}
Resource<R> resource = null;
try {
resource = decodeFromData(currentFetcher, currentData, currentDataSource);
} catch (GlideException e) {
e.setLoggingDetails(currentAttemptingKey, currentDataSource);
throwables.add(e);
}
if (resource != null) {
notifyEncodeAndRelease(resource, currentDataSource);
} else {
runGenerators();
}
}
创建一个Resource类型的变量,通过decodeFromData方法把输入流解码并返回给resource,由此可也看出,解码主要是在decodeFromData方法中:
private <Data> Resource<R> decodeFromData(DataFetcher<?> fetcher, Data data,
DataSource dataSource) throws GlideException {
try {
if (data == null) {
return null;
}
long startTime = LogTime.getLogTime();
Resource<R> result = decodeFromFetcher(data, dataSource);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Decoded result " + result, startTime);
}
return result;
} finally {
//关闭流
fetcher.cleanup();
}
}
在上面获取流对象后回调,并没有进行关闭操作,是因为还需要对流进行解码操作,等操作结束后再关闭。这就是为什么在这个方法才关闭流对象。
又调用decodeFromFetcher方法来进行解码返回一个Resource:
private <Data> Resource<R> decodeFromFetcher(Data data, DataSource dataSource)
throws GlideException {
LoadPath<Data, ?, R> path = decodeHelper.getLoadPath((Class<Data>) data.getClass());
return runLoadPath(data, dataSource, path);
}
这里获取到data.getClass,这个Class就是DirectByteBuffer.class,进到decodeHelper.getLoadPath()方法看一下:
<Data> LoadPath<Data, ?, Transcode> getLoadPath(Class<Data> dataClass) {
return glideContext.getRegistry().getLoadPath(dataClass, resourceClass, transcodeClass);
}
public <Data, TResource, Transcode> LoadPath<Data, TResource, Transcode> getLoadPath(
@NonNull Class<Data> dataClass, @NonNull Class<TResource> resourceClass,
@NonNull Class<Transcode> transcodeClass) {
LoadPath<Data, TResource, Transcode> result =
loadPathCache.get(dataClass, resourceClass, transcodeClass);
if (loadPathCache.isEmptyLoadPath(result)) {
return null;
} else if (result == null) {
//调用getDecodePaths方法
List<DecodePath<Data, TResource, Transcode>> decodePaths =
getDecodePaths(dataClass, resourceClass, transcodeClass);
if (decodePaths.isEmpty()) {
result = null;
} else {
result = new LoadPath<>(
dataClass, resourceClass, transcodeClass, decodePaths, throwableListPool);
}
loadPathCache.put(dataClass, resourceClass, transcodeClass, result);
}
return result;
}
从上面分析知道resourceClass是Object.class,transcodeClass则是Drawable.class。
首先从loadPathCache缓存中获取LoadPath对象,如果没有则调用getDecodePaths方法进行获取:
private <Data, TResource, Transcode> List<DecodePath<Data, TResource, Transcode>> getDecodePaths(
@NonNull Class<Data> dataClass, @NonNull Class<TResource> resourceClass,
@NonNull Class<Transcode> transcodeClass) {
List<DecodePath<Data, TResource, Transcode>> decodePaths = new ArrayList<>();
//获取registeredResourceClasses
List<Class<TResource>> registeredResourceClasses =
decoderRegistry.getResourceClasses(dataClass, resourceClass);
for (Class<TResource> registeredResourceClass : registeredResourceClasses) {
//获取registeredTranscodeClasses
List<Class<Transcode>> registeredTranscodeClasses =
transcoderRegistry.getTranscodeClasses(registeredResourceClass, transcodeClass);
for (Class<Transcode> registeredTranscodeClass : registeredTranscodeClasses) {
//获取decoders
List<ResourceDecoder<Data, TResource>> decoders =
decoderRegistry.getDecoders(dataClass, registeredResourceClass);
//获取transcoder
ResourceTranscoder<TResource, Transcode> transcoder =
transcoderRegistry.get(registeredResourceClass, registeredTranscodeClass);
@SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
DecodePath<Data, TResource, Transcode> path =
new DecodePath<>(dataClass, registeredResourceClass, registeredTranscodeClass,
decoders, transcoder, throwableListPool);
decodePaths.add(path);
}
}
return decodePaths;
}
先从decoderRegistry.getResourceClasses方法中获取已经注册的registeredResourceClasses。这个在上面已经分析过了,只是上面分析时dataClass是String类型
而这次是DirectByteBuffer类型,这个DirectByteBuffer类型就是InputStream流经过缓存之后转化的。直接去解码模块找一下:
append(Registry.BUCKET_BITMAP, ByteBuffer.class, Bitmap.class, byteBufferBitmapDecoder)
append(Registry.BUCKET_GIF, ByteBuffer.class, GifDrawable.class, byteBufferGifDecoder)
append(Registry.BUCKET_BITMAP_DRAWABLE,ByteBuffer.class,BitmapDrawable.class,new BitmapDrawableDecoder<>(resources, byteBufferBitmapDecoder))
拿到的就是GifDrawable、BitmapDrawable、Bitmap。
然后循环registeredResourceClasses,调用transcoderRegistry.getTranscodeClasses获取去registeredTranscodeClasses,这个上面也分析过了,拿到的就是Drawable
然后获取decoders解码:
byteBufferBitmapDecoder、byteBufferGifDecoder、BitmapDrawableDecoder
获取transcoder转码:
BitmapDrawableTranscoder、UnitTranscoder、UnitTranscoder
最后放到decodePaths集合中,返回。再回到glideContext.getRegistry().getLoadPath,继续执行就是将集合封装成了LoadPath对象。
然后回到decodeFromFetcher方法中,可以看到调用了runLoadPath(data, dataSource, path)方法:
private <Data, ResourceType> Resource<R> runLoadPath(Data data, DataSource dataSource,
LoadPath<Data, ResourceType, R> path) throws GlideException {
Options options = getOptionsWithHardwareConfig(dataSource);
DataRewinder<Data> rewinder = glideContext.getRegistry().getRewinder(data);
try {
// ResourceType in DecodeCallback below is required for compilation to work with gradle.
return path.load(
rewinder, options, width, height, new DecodeCallback<ResourceType>(dataSource));
} finally {
rewinder.cleanup();
}
}
调用glideContext.getRegistry()获取Registry对象,然后调用Registry的getRewinder获取装置器,跟进去看看:
public <X> DataRewinder<X> getRewinder(@NonNull X data) {
return dataRewinderRegistry.build(data);
}
看一下dataRewinderRegistry的内容
register(new ByteBufferRewinder.Factory())
register(new InputStreamRewinder.Factory(arrayPool))
获取到factory之后调用dataRewinderRegistry.register方法注册到Map集合rewinders中去:
public synchronized void register(@NonNull DataRewinder.Factory<?> factory) {
rewinders.put(factory.getDataClass(), factory);
}
再来看看factory.getDataClass()都获取到哪些key:
在ByteBufferRewinder.Factory中调用getDataClass()获取的key是ByteBuffer.class
在InputStreamRewinder.Factory中调用getDataClass()获取的key是InputStream.class
返回到getRewinder方法中,调用dataRewinderRegistry对象的build方法到底做了什么:
public synchronized <T> DataRewinder<T> build(@NonNull T data) {
Preconditions.checkNotNull(data);
DataRewinder.Factory<T> result = (DataRewinder.Factory<T>) rewinders.get(data.getClass());
if (result == null) {
for (DataRewinder.Factory<?> registeredFactory : rewinders.values()) {
if (registeredFactory.getDataClass().isAssignableFrom(data.getClass())) {
result = (DataRewinder.Factory<T>) registeredFactory;
break;
}
}
}
if (result == null) {
result = (DataRewinder.Factory<T>) DEFAULT_FACTORY;
}
return result.build(data);
}
在build的方法中总共做了四件事:
<1> 从rewinders集合中获取到和data.getClass()相匹配的Factory对象,从上面的分析中,知道rewinders注册的只有两个key,分别是ByteBuffer.class和InputStream.class,
data.getClass()是一个ByteBuffer.class,由此可以匹配成功。这个result就是ByteBufferRewinder.Factory对象。
<2> 假如result没有匹配成功的话,也就是没有通过key匹配成功,那么就进行遍历rewinders集合,通过values值进行匹配,把匹配成功的Factory对象再赋值给result。
<3> 假如通过键key和值values都没有匹配成功,那么也不要紧,直接使用默认的DEFAULT_FACTORY
<4> 最后调用result的build方法。
通过键key直接已匹配成功,ByteBufferRewinder.Factory对象,那么来看看调用它的build方法做了什么事情:
public DataRewinder<ByteBuffer> build(ByteBuffer data) {
return new ByteBufferRewinder(data);
}
直接的返回了一个ByteBufferRewinder对象.再次定位到DecodeJob类中的runLoadPath方法,在获取到ByteBufferRewinder后,它会调用path.load方法并返回Resource资源类
public Resource<Transcode> load(DataRewinder<Data> rewinder, @NonNull Options options, int width,
int height, DecodePath.DecodeCallback<ResourceType> decodeCallback) throws GlideException {
List<Throwable> throwables = Preconditions.checkNotNull(listPool.acquire());
try {
return loadWithExceptionList(rewinder, options, width, height, decodeCallback, throwables);
} finally {
listPool.release(throwables);
}
}
private Resource<Transcode> loadWithExceptionList(DataRewinder<Data> rewinder,
@NonNull Options options,
int width, int height, DecodePath.DecodeCallback<ResourceType> decodeCallback,
List<Throwable> exceptions) throws GlideException {
Resource<Transcode> result = null;
//noinspection ForLoopReplaceableByForEach to improve perf
for (int i = 0, size = decodePaths.size(); i < size; i++) {
DecodePath<Data, ResourceType, Transcode> path = decodePaths.get(i);
try {
//解码
result = path.decode(rewinder, width, height, options, decodeCallback);
} catch (GlideException e) {
exceptions.add(e);
}
if (result != null) {
break;
}
}
if (result == null) {
throw new GlideException(failureMessage, new ArrayList<>(exceptions));
}
return result;
}
这个loadWithExceptionList方法首先遍历decodePaths,获取一个DecodePath调用decode方法进行解吗:
public Resource<Transcode> decode(DataRewinder<DataType> rewinder, int width, int height,
@NonNull Options options, DecodeCallback<ResourceType> callback) throws GlideException {
//解码获取资源
Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);
Resource<ResourceType> transformed = callback.onResourceDecoded(decoded);
return transcoder.transcode(transformed, options);
}
@NonNull
private Resource decodeResource(DataRewinder rewinder, int width,
int height, @NonNull Options options) throws GlideException {
List exceptions = Preconditions.checkNotNull(listPool.acquire());
try {
//解码
return decodeResourceWithList(rewinder, width, height, options, exceptions);
} finally {
listPool.release(exceptions);
}
}
decode方法中调用decodeResource方法,然后在调用decodeResourceWithList方法真正的开始解码:
@NonNull
private Resource<ResourceType> decodeResourceWithList(DataRewinder<DataType> rewinder, int width,
int height, @NonNull Options options, List<Throwable> exceptions) throws GlideException {
Resource<ResourceType> result = null;
//循环解码器
for (int i = 0, size = decoders.size(); i < size; i++) {
ResourceDecoder<DataType, ResourceType> decoder = decoders.get(i);
try {
//获取DataType
DataType data = rewinder.rewindAndGet();
//匹配解码器
if (decoder.handles(data, options)) {
data = rewinder.rewindAndGet();
//开始解码
result = decoder.decode(data, width, height, options);
}
} catch (IOException | RuntimeException | OutOfMemoryError e) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Failed to decode data for " + decoder, e);
}
exceptions.add(e);
}
//有一个匹配到就跳出循环
if (result != null) {
break;
}
}
//匹配不成功,抛出异常
if (result == null) {
throw new GlideException(failureMessage, new ArrayList<>(exceptions));
}
return result;
}
<1> 这里面的decoders里面只有一个解码器byteBufferGifDecoder
<2> 获取DataType ,进入rewinder.rewindAndGet();
public ByteBuffer rewindAndGet() {
buffer.position(0);
return buffer;
}
<3> 通过decoder.handles(data, options)方法来过滤掉不相匹配的解码器,看一下byteBufferGifDecoder中的handles方法:
public boolean handles(@NonNull InputStream source, @NonNull Options options) throws IOException {
return !options.get(GifOptions.DISABLE_ANIMATION)
&& ImageHeaderParserUtils.getType(parsers, source, byteArrayPool) == ImageType.GIF;
}
可以看到这个解码器适用于处理GIF格式的图片,而这里是普通的图片。所以匹配不成功。抛出异常。不处理,继续回到loadWithExceptionList方法。
遍历获取下一个DecodePath。这次获取的是byteBufferBitmapDecoder。来看一下byteBufferBitmapDecoder解码器的handles方法:
public boolean handles(@NonNull ByteBuffer source, @NonNull Options options) {
return downsampler.handles(source);
}
public boolean handles(@SuppressWarnings("unused") ByteBuffer byteBuffer) {
return true;
}
可以看到downsampler.handles(source)总是返回true。匹配成功。调用decoder.decode开始解码
public Resource<Bitmap> decode(@NonNull ByteBuffer source, int width, int height,
@NonNull Options options)
throws IOException {
InputStream is = ByteBufferUtil.toStream(source);
return downsampler.decode(is, width, height, options);
}
将ByteBuffer转为InputStream流对象,调用downsampler.decode进行解码
public Resource<Bitmap> decode(InputStream is, int outWidth, int outHeight,
Options options) throws IOException {
return decode(is, outWidth, outHeight, options, EMPTY_CALLBACKS);
}
public Resource<Bitmap> decode(InputStream is, int requestedWidth, int requestedHeight,
Options options, DecodeCallbacks callbacks) throws IOException {
Preconditions.checkArgument(is.markSupported(), "You must provide an InputStream that supports"
+ " mark()");
byte[] bytesForOptions = byteArrayPool.get(ArrayPool.STANDARD_BUFFER_SIZE_BYTES, byte[].class);
BitmapFactory.Options bitmapFactoryOptions = getDefaultOptions();
bitmapFactoryOptions.inTempStorage = bytesForOptions;
DecodeFormat decodeFormat = options.get(DECODE_FORMAT);
DownsampleStrategy downsampleStrategy = options.get(DownsampleStrategy.OPTION);
boolean fixBitmapToRequestedDimensions = options.get(FIX_BITMAP_SIZE_TO_REQUESTED_DIMENSIONS);
boolean isHardwareConfigAllowed = options.get(ALLOW_HARDWARE_CONFIG) != null && options.get(ALLOW_HARDWARE_CONFIG);
try {
Bitmap result = decodeFromWrappedStreams(is, bitmapFactoryOptions,
downsampleStrategy, decodeFormat, isHardwareConfigAllowed, requestedWidth,
requestedHeight, fixBitmapToRequestedDimensions, callbacks);
return BitmapResource.obtain(result, bitmapPool);
} finally {
releaseOptions(bitmapFactoryOptions);
byteArrayPool.put(bytesForOptions);
}
}
就是通过requestedWidth、requestedHeight、options等将流进行一些操作,最终返回了Resource对象。解码完后。
回到DecodePath.decode方法,可以看到调用transcoder.transcode(transformed, options),
在上面的分析中可以知道byteBufferBitmapDecoder对应的transcoder转码器是BitmapDrawableTranscoder,进入它的transcode()方法看一下:
public Resource<BitmapDrawable> transcode(@NonNull Resource<Bitmap> toTranscode,
@NonNull Options options) {
return LazyBitmapDrawableResource.obtain(resources, toTranscode);
}
public static Resource<BitmapDrawable> obtain(
@NonNull Resources resources, @Nullable Resource<Bitmap> bitmapResource) {
if (bitmapResource == null) {
return null;
}
return new LazyBitmapDrawableResource(resources, bitmapResource);
}
private LazyBitmapDrawableResource(@NonNull Resources resources,
@NonNull Resource<Bitmap> bitmapResource) {
this.resources = Preconditions.checkNotNull(resources);
this.bitmapResource = Preconditions.checkNotNull(bitmapResource);
}
把Bitmap封装到LazyBitmapDrawableResource对象中进行返回。到这里其实已完成了解码和封装。再次loadWithExceptionList方法,
如果返回的结果不为空的话就跳出循环,不再执行下一个DecodePath,然后返回。一直往上回到DecodeJob.decodeFromRetrievedData(),
如果resource不为null的话,就调用notifyEncodeAndRelease(resource, currentDataSource);方法:
private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {
if (resource instanceof Initializable) {
((Initializable) resource).initialize();
}
Resource<R> result = resource;
LockedResource<R> lockedResource = null;
if (deferredEncodeManager.hasResourceToEncode()) {
lockedResource = LockedResource.obtain(resource);
result = lockedResource;
}
notifyComplete(result, dataSource);
stage = Stage.ENCODE;
try {
if (deferredEncodeManager.hasResourceToEncode()) {
deferredEncodeManager.encode(diskCacheProvider, options);
}
} finally {
if (lockedResource != null) {
lockedResource.unlock();
}
}
onEncodeComplete();
}
调用notifyComplete方法:
private void notifyComplete(Resource<R> resource, DataSource dataSource) {
setNotifiedOrThrow();
callback.onResourceReady(resource, dataSource);
}
调用了callback.onResourceReady(resource, dataSource);方法,这个callback是EngineJob实现:
public void onResourceReady(Resource<R> resource, DataSource dataSource) {
synchronized (this) {
this.resource = resource;
this.dataSource = dataSource;
}
notifyCallbacksOfResult();
}
调用了notifyCallbacksOfResult()方法
void notifyCallbacksOfResult() {
ResourceCallbacksAndExecutors copy;
Key localKey;
EngineResource<?> localResource;
synchronized (this) {
stateVerifier.throwIfRecycled();
if (isCancelled) {
resource.recycle();
release();
return;
} else if (cbs.isEmpty()) {
throw new IllegalStateException("Received a resource without any callbacks to notify");
} else if (hasResource) {
throw new IllegalStateException("Already have resource");
}
engineResource = engineResourceFactory.build(resource, isCacheable);
hasResource = true;
copy = cbs.copy();
incrementPendingCallbacks(copy.size() + 1);
localKey = key;
localResource = engineResource;
}
listener.onEngineJobComplete(this, localKey, localResource);
for (final ResourceCallbackAndExecutor entry : copy) {
entry.executor.execute(new CallResourceReady(entry.cb));
}
decrementPendingCallbacks();
}
<1> 调用engineResourceFactory.build(resource, isCacheable)将resource封装
<2> entry.executor.execute方法切换回主线程,这个executor就是最开始调用RequestBuilder.into方法是创建的线程池对象。
看一下execute(new CallResourceReady(entry.cb))中的CallResourceReady对象。
private class CallResourceReady implements Runnable {
private final ResourceCallback cb;
CallResourceReady(ResourceCallback cb) {
this.cb = cb;
}
@Override
public void run() {
synchronized (EngineJob.this) {
if (cbs.contains(cb)) {
engineResource.acquire();
callCallbackOnResourceReady(cb);
removeCallback(cb);
}
decrementPendingCallbacks();
}
}
}
调用了callCallbackOnResourceReady方法:
synchronized void callCallbackOnResourceReady(ResourceCallback cb) {
try {
cb.onResourceReady(engineResource, dataSource);
} catch (Throwable t) {
throw new CallbackException(t);
}
}
这个cb是ResourceCallback的接口,也就是SingleRequest就实现了这个接口:
public synchronized void onResourceReady(Resource<?> resource, DataSource dataSource) {
stateVerifier.throwIfRecycled();
loadStatus = null;
if (resource == null) {
GlideException exception = new GlideException("Expected to receive a Resource<R> with an "
+ "object of " + transcodeClass + " inside, but instead got null.");
onLoadFailed(exception);
return;
}
//获取资源
Object received = resource.get();
if (received == null || !transcodeClass.isAssignableFrom(received.getClass())) {
releaseResource(resource);
GlideException exception = new GlideException("Expected to receive an object of "
+ transcodeClass + " but instead" + " got "
+ (received != null ? received.getClass() : "") + "{" + received + "} inside" + " "
+ "Resource{" + resource + "}."
+ (received != null ? "" : " " + "To indicate failure return a null Resource "
+ "object, rather than a Resource object containing null data."));
onLoadFailed(exception);
return;
}
if (!canSetResource()) {
releaseResource(resource);
// We can't put the status to complete before asking canSetResource().
status = Status.COMPLETE;
return;
}
//调用重载onResourceReady
onResourceReady((Resource<R>) resource, (R) received, dataSource);
}
首先获取资源,从上面的分析知道resource是engineResource对象,看一下get方法:
public Z get() {
return resource.get();
}
这个方法又调用没有封装成engineResource对象前的resource的get方法,也就是LazyBitmapDrawableResource对象
public BitmapDrawable get() {
return new BitmapDrawable(resources, bitmapResource.get());
}
这个方法就直接将resources也就是将Bimap封装成了BitmapDrawable对象。资源对象获取成功之后,有调用了一个重载的onResourceReady方法
private synchronized void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {
// We must call isFirstReadyResource before setting status.
boolean isFirstResource = isFirstReadyResource();
status = Status.COMPLETE;
this.resource = resource;
if (glideContext.getLogLevel() <= Log.DEBUG) {
Log.d(GLIDE_TAG, "Finished loading " + result.getClass().getSimpleName() + " from "
+ dataSource + " for " + model + " with size [" + width + "x" + height + "] in "
+ LogTime.getElapsedMillis(startTime) + " ms");
}
isCallingCallbacks = true;
try {
boolean anyListenerHandledUpdatingTarget = false;
if (requestListeners != null) {
for (RequestListener<R> listener : requestListeners) {
anyListenerHandledUpdatingTarget |=
listener.onResourceReady(result, model, target, dataSource, isFirstResource);
}
}
anyListenerHandledUpdatingTarget |= targetListener != null
&& targetListener.onResourceReady(result, model, target, dataSource, isFirstResource);
if (!anyListenerHandledUpdatingTarget) {
Transition<? super R> animation = animationFactory.build(dataSource, isFirstResource);
target.onResourceReady(result, animation);
}
} finally {
isCallingCallbacks = false;
}
notifyLoadSuccess();
}
在onResourceReady方法中调用了target.onResourceReady(result, animation);在load方法中已讲解过,就是DrawableImageViewTarget对象,
调用它的onResourceReady会转移到父类ImageViewTarget中
public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {
if (transition == null || !transition.transition(resource, this)) {
setResourceInternal(resource);
} else {
maybeUpdateAnimatable(resource);
}
}
然后在调用setResourceInternal方法:
private void setResourceInternal(@Nullable Z resource) {
setResource(resource);
maybeUpdateAnimatable(resource);
}
setResource是抽象方法,由它的子类实现,我们在回到DrawableImageViewTarget中:
protected void setResource(@Nullable Drawable resource) {
view.setImageDrawable(resource);
}
到这里直接调用view进行设置图片了,这个view就是我们Imageview了,整个加载的图片的过程就结束了。