前言
由名字可以看出这是一个解码的帮助类,里面缓存了LoadData和Key,以及很多从DecoderJob传递过来的参数。它的主要作用是提供解码所需要的的数据,并不进行实际的解码操作。
final class DecodeHelper<Transcode> {
private final List<LoadData<?>> loadData = new ArrayList<>();
private final List<Key> cacheKeys = new ArrayList<>();
private Map<Class<?>, Transformation<?>> transformations; //在BaseRequestOptions中为CachedHashCodeArrayMap
private Object model; //String
private Class<?> resourceClass; //Object.class
private Class<Transcode> transcodeClass; //Drawable.class
}
getCacheKeys()
在这里获取缓存到的key,如果没有则会先获取LoadData,再获取LoadData里面的key。在Glide源码解析之RequestBuilder我们在load()传入的为String类型的 url,所以我们的model为String,则最终cacheKeys会包含GlideUrl(实现了Key接口),在下面会进行分析。
List<Key> getCacheKeys() {
if (!isCacheKeysSet) {
isCacheKeysSet = true;
cacheKeys.clear();
List<LoadData<?>> loadData = getLoadData();
//将LoadData里面的key都缓存起来
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;
}
getLoadData()
LoadData是一个封装了Key、List<key>、DataFetcher<Data>的类,里面没有任何操作。首先会获取已注册的加载器中所有可以加载当前模型的ModelLoader,再由它调用buildLoadData()生成LoadData。这里最终获取到的modelLoaders会包含HttpGlideUrlLoader,它最终会build一个Key为GlideUrl和DataFetcher为HttpUrlFetcher的LoadData出来。
class LoadData<Data> {
public final Key sourceKey;
public final List<Key> alternateKeys; //默认会赋值为Collections.<Key>emptyList()
public final DataFetcher<Data> fetcher;
}
List<LoadData<?>> getLoadData() {
if (!isLoadDataSet) {
isLoadDataSet = true;
loadData.clear();
List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model);
for (int i = 0, size = modelLoaders.size(); i < size; i++) {
ModelLoader<Object, ?> modelLoader = modelLoaders.get(i);
LoadData<?> current =
modelLoader.buildLoadData(model, width, height, options);
if (current != null) {
loadData.add(current);
}
}
}
return loadData;
}
getModelLoaders()
获取能处理当前类型的ModelLoaders,而ModelLoader实际是由MultiModelLoaderFactory去build出来的。在MultiModelLoaderFactory中,将ModelLoaderFactory、modelClass(要加载的model,这里是String.class)、dataClass(加载的数据类型,例如InputStream.class)包装成一个Entry,就像上面的LoadData那样。而Entry的来源则是在Glide初始化的时候,由Registry设置给ModelLoaderRegistry,再设置给MultiModelLoaderFactory。
//Registry
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
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();
for (int i = 0; i < size; i++) {
ModelLoader<A, ?> loader = modelLoaders.get(i);
if (loader.handles(model)) { //是否能处理model类型
if (isEmpty) {
filteredLoaders = new ArrayList<>(size - i);
isEmpty = false;
}
filteredLoaders.add(loader);
}
}
return filteredLoaders;
}
//首先从缓存获取,获取不到再build一个新的,并存入缓存
private synchronized <A> List<ModelLoader<A, ?>> getModelLoadersForClass(
@NonNull Class<A> modelClass) {
List<ModelLoader<A, ?>> loaders = cache.get(modelClass);
if (loaders == null) {
loaders = Collections.unmodifiableList(multiModelLoaderFactory.build(modelClass));
cache.put(modelClass, loaders);
}
return loaders;
}
public class MultiModelLoaderFactory {
private final List<Entry<?, ?>> entries = new ArrayList<>();
private static class Entry<Model, Data> {
private final Class<Model> modelClass;
@Synthetic
final Class<Data> dataClass;
@Synthetic
final ModelLoaderFactory<? extends Model, ? extends Data> factory;
public Entry(
@NonNull Class<Model> modelClass,
@NonNull Class<Data> dataClass,
@NonNull ModelLoaderFactory<? extends Model, ? extends Data> factory) {
this.modelClass = modelClass;
this.dataClass = dataClass;
this.factory = factory;
}
public boolean handles(@NonNull Class<?> modelClass) {
return this.modelClass.isAssignableFrom(modelClass); //this.modelClass是否是modelClass的父类或者接口
}
}
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)) {
//由于modelClass是String.class,所以最终只有modelClass为String.class的Entry才能执行到这里。
//比如有Entry(String.class, InputStream.class, new StringLoader.StreamFactory())
//所以loaders会add一个由StreamFactory去build出来的StringLoader。
alreadyUsedEntries.add(entry);
loaders.add(this.<Model, Object>build(entry));
alreadyUsedEntries.remove(entry);
}
}
return loaders;
} catch (Throwable t) {
alreadyUsedEntries.clear();
throw t;
}
}
private <Model, Data> ModelLoader<Model, Data> build(@NonNull Entry<?, ?> entry) {
return (ModelLoader<Model, Data>) Preconditions.checkNotNull(entry.factory.build(this));
}
//Entry的来源
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);
}
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);
}
}
//ModelLoaderRegistry
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();
}
//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;
}
//Glide
Glide(){
registry
.append(String.class, InputStream.class, new DataUrlLoader.StreamFactory<String>())
.append(Uri.class, InputStream.class, new HttpUriLoader.Factory())
.append(String.class, InputStream.class, new StringLoader.StreamFactory())
.append(String.class, ParcelFileDescriptor.class, new StringLoader.FileDescriptorFactory())
.append(GlideUrl.class, InputStream.class, new HttpGlideUrlLoader.Factory())
}
上面说到会由StreamFactory去build一个StringLoader,而StringLoader的构造函数又传入了一个由MultiModelLoaderFactory去build出来的ModelLoader。由于传给它的是Uri.class和InputStream.class,我们去Glide的构造函数找到对应的factory为HttpUriLoader的内部类Factory。它build了一个HttpUriLoader,但同时它的构造函数又传入一个新的ModelLoader,根据类型不难找到实际为HttpGlideUrlLoader。
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));
}
}
//MultiModelLoaderFactory
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)) {
//匹配Uri.class和InputStream.class的Entry(Uri.class, InputStream.class, new HttpUriLoader.Factory())
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;
}
}
//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));
}
}
//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);
}
}
StringLoader
StringLoader实现了ModelLoader接口,里面主要是两个方法,handles()在上面ModelLoaderRegistry.getModelLoaders()进行了判断,这里主要看下看下buildLoadData()。
由上面分析可知StringLoader传入了HttpUriLoader,而HttpUriLoader又传入了HttpGlideUrlLoader,所以这里实际上是使用了代理模式,将实际生成LoadData的操作最终交给了HttpGlideUrlLoader。所以最终生成的LoadData的sourceKey为GlideUrl,fetcher为HttpUrlFetcher。
public class StringLoader<Data> implements ModelLoader<String, Data> {
private final ModelLoader<Uri, Data> uriLoader;
public StringLoader(ModelLoader<Uri, Data> uriLoader) {
this.uriLoader = uriLoader;
}
@Override
public LoadData<Data> buildLoadData(@NonNull String model, int width, int height,
@NonNull Options options) {
Uri uri = parseUri(model);
if (uri == null || !uriLoader.handles(uri)) {
return null;
}
return uriLoader.buildLoadData(uri, width, height, options);
}
//是否能处理String类型的model
@Override
public boolean handles(@NonNull String model) {
return true;
}
}
//HttpUriLoader
public LoadData<InputStream> buildLoadData(@NonNull Uri model, int width, int height,
@NonNull Options options) {
//urlLoader为HttpGlideUrlLoader
return urlLoader.buildLoadData(new GlideUrl(model.toString()), width, height, options);
}
//HttpGlideUrlLoader
public LoadData<InputStream> buildLoadData(@NonNull GlideUrl model, int width, int height,
@NonNull Options options) {
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));
}
getRegisteredResourceClasses()
上面说过model.getClass()为String.class,在RequestBuilder的父类BaseRequestOptions中resourceClass默认为Object.class,在Glide源码解析之RequestBuilder我们在load()传入的为String Url,里面会调用asDrawable(),所以这里transcodeClass为Drawable.class。
首先会先从缓存中获取,如果没有则调用modelLoaderRegistry.getDataClasses(modelClass)获取String.class对应的dataClass,然后遍历它,再调用decoderRegistry.getResourceClasses(dataClass, resourceClass)获取对应已注册的resourceClass,最后也遍历registeredResourceClasses,根据registeredResourceClass,和transcodeClass获取最终能处理的registeredResourceClass。所以最后的List会包含Drawable.class。
List<Class<?>> getRegisteredResourceClasses() {
return glideContext.getRegistry()
.getRegisteredResourceClasses(model.getClass(), resourceClass, transcodeClass);
}
//Registry
public <Model, TResource, Transcode> List<Class<?>> getRegisteredResourceClasses(
@NonNull Class<Model> modelClass /*String*/,
@NonNull Class<TResource> resourceClass /*Object*/,
@NonNull Class<Transcode> transcodeClass /*Drawable*/) {
List<Class<?>> result =
modelToResourceClassCache.get(modelClass, resourceClass, transcodeClass);
if (result == null) {
result = new ArrayList<>();
List<Class<?>> dataClasses = modelLoaderRegistry.getDataClasses(modelClass); //InputStream.class、ParcelFileDescriptor.class和AssetFileDescriptor.class
for (Class<?> dataClass : dataClasses) {
List<? extends Class<?>> registeredResourceClasses =
decoderRegistry.getResourceClasses(dataClass, resourceClass); //GifDrawable.class、Bitmap.class、BitmapDrawable.class
for (Class<?> registeredResourceClass : registeredResourceClasses) {
List<Class<Transcode>> registeredTranscodeClasses = transcoderRegistry
.getTranscodeClasses(registeredResourceClass, transcodeClass); //Drawable.class
if (!registeredTranscodeClasses.isEmpty() && !result.contains(registeredResourceClass)) {
result.add(registeredResourceClass); //Drawable.class
}
}
}
modelToResourceClassCache.put(
modelClass, resourceClass, transcodeClass, Collections.unmodifiableList(result));
}
return result;
}
getDataClasses()
还是和上面获取ModelLoader一样,这里也是根据Entry中是否能handles()对应的modelClass来获取dataClasses。
由于modelClass为String.class,所以最终返回的List会包含InputStream.class、ParcelFileDescriptor.class和AssetFileDescriptor.class。
//ModelLoaderRegistry
public synchronized List<Class<?>> getDataClasses(@NonNull Class<?> modelClass) {
return multiModelLoaderFactory.getDataClasses(modelClass);
}
//MultiModelLoaderFactory
synchronized List<Class<?>> getDataClasses(@NonNull Class<?> modelClass) {
List<Class<?>> result = new ArrayList<>();
for (Entry<?, ?> entry : entries) {
//上面说了Entry实际会在Glide的构造函数通过Registry的append()赋值,那么只要找出哪些modelClass为String.class对应的dataClass就行了。
if (!result.contains(entry.dataClass) && entry.handles(modelClass)) {
result.add(entry.dataClass);
}
}
return result;
}
Glide(){
registry
.append(String.class, InputStream.class, new DataUrlLoader.StreamFactory<String>())
.append(String.class, InputStream.class, new StringLoader.StreamFactory())
.append(String.class, ParcelFileDescriptor.class, new StringLoader.FileDescriptorFactory())
.append(
String.class, AssetFileDescriptor.class, new StringLoader.AssetFileDescriptorFactory())
}
getResourceClasses()
第一个参数为InputStream.class,第二个参数为Drawable.class。由于decoders保存了所有在Glide构造函数中注册的bucket,所以在Glide的构造函数中找出对应dataClass为InputStream的resource即可。最终这里返回的List会包含GifDrawable.class、Bitmap.class、BitmapDrawable.class。
//ResouceDecoderRegistry
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(entry.resourceClass)) {
result.add((Class<R>) entry.resourceClass);
}
}
}
return result;
}
ResourceDecoderRegistry
资源解码注册表,和MultiModelLoaderFactory作用类似,它们里面都有一个Entry保存了几个变量,并且都有handles()用来判断这个Entry能否处理对应的类型。
ResourceDecoderRegistry里面有一个bucketPriorityList,它是在Registry在的构造函数里赋值的。同时还用Map来保存了Entry,它则是在Glide的构造函数里通过Registry赋值的。
public class ResourceDecoderRegistry {
private final List<String> bucketPriorityList = new ArrayList<>();
private final Map<String, List<Entry<?, ?>>> decoders = new HashMap<>();
public synchronized void setBucketPriorityList(@NonNull List<String> buckets) {
List<String> previousBuckets = new ArrayList<>(bucketPriorityList);
bucketPriorityList.clear();
bucketPriorityList.addAll(buckets);
//如果之前bucketPriorityList有的元素是现在没有,则同样保存下来
for (String previousBucket : previousBuckets) {
if (!buckets.contains(previousBucket)) {
bucketPriorityList.add(previousBucket);
}
}
}
private static class Entry<T, R> {
private final Class<T> dataClass;
@Synthetic
final Class<R> resourceClass;
@Synthetic
final ResourceDecoder<T, R> decoder;
public Entry(@NonNull Class<T> dataClass, @NonNull Class<R> resourceClass,
ResourceDecoder<T, R> decoder) {
this.dataClass = dataClass;
this.resourceClass = resourceClass;
this.decoder = decoder;
}
//由于resourceClass默认为Object.class,所以第二个判断为true,只需要判断dataClass就行了
public boolean handles(@NonNull Class<?> dataClass, @NonNull Class<?> resourceClass) {
return this.dataClass.isAssignableFrom(dataClass) && resourceClass
.isAssignableFrom(this.resourceClass);
}
}
}
public class Registry {
public static final String BUCKET_GIF = "Gif";
public static final String BUCKET_BITMAP = "Bitmap";
public static final String BUCKET_BITMAP_DRAWABLE = "BitmapDrawable";
private static final String BUCKET_PREPEND_ALL = "legacy_prepend_all";
private static final String BUCKET_APPEND_ALL = "legacy_append";
public Registry() {
setResourceDecoderBucketPriorityList(
Arrays.asList(BUCKET_GIF, BUCKET_BITMAP, BUCKET_BITMAP_DRAWABLE));
}
//所以ResourceDecoderRegistry的bucketPriorityList的值为[BUCKET_PREPEND_ALL,BUCKET_GIF,BUCKET_BITMAP,BUCKET_BITMAP_DRAWABLE,BUCKET_APPEND_ALL]
public final Registry setResourceDecoderBucketPriorityList(@NonNull List<String> buckets) {
List<String> modifiedBuckets = new ArrayList<>(buckets.size());
modifiedBuckets.addAll(buckets);
modifiedBuckets.add(0, BUCKET_PREPEND_ALL);
modifiedBuckets.add(BUCKET_APPEND_ALL);
decoderRegistry.setBucketPriorityList(modifiedBuckets);
return this;
}
}
decoders以bucket为key,List<Entry<?, ?>>为value,在Glide的构造函数中通过Registry赋值。
//ResouceDecoderRegistry
private synchronized List<Entry<?, ?>> getOrAddEntryList(@NonNull String bucket) {
if (!bucketPriorityList.contains(bucket)) {
bucketPriorityList.add(bucket);
}
List<Entry<?, ?>> entries = decoders.get(bucket);
if (entries == null) {
entries = new ArrayList<>();
decoders.put(bucket, entries);
}
return entries;
}
public synchronized <T, R> void append(@NonNull String bucket,
@NonNull ResourceDecoder<T, R> decoder,
@NonNull Class<T> dataClass, @NonNull Class<R> resourceClass) {
//将Entry添加到key为bucket的List里
getOrAddEntryList(bucket).add(new Entry<>(dataClass, resourceClass, decoder));
}
//Registry
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;
}
Glide(){
registry
/* Bitmaps */
.append(Registry.BUCKET_BITMAP, InputStream.class, Bitmap.class, streamBitmapDecoder)
/* BitmapDrawables */
.append(
Registry.BUCKET_BITMAP_DRAWABLE,
InputStream.class,
BitmapDrawable.class,
new BitmapDrawableDecoder<>(resources, streamBitmapDecoder))
/* GIFs */
.append(
Registry.BUCKET_GIF,
InputStream.class,
GifDrawable.class,
new StreamGifDecoder(imageHeaderParsers, byteBufferGifDecoder, arrayPool))
}
getTranscodeClasses()
熟悉的名字,熟悉的味道,这个类比上面那两个简单,自己按照规则看下就懂了。
public class TranscoderRegistry {
private final List<Entry<?, ?>> transcoders = new ArrayList<>();
public synchronized <Z, R> void register(
@NonNull Class<Z> decodedClass, @NonNull Class<R> transcodedClass,
@NonNull ResourceTranscoder<Z, R> transcoder) {
transcoders.add(new Entry<>(decodedClass, transcodedClass, transcoder));
}
public synchronized <Z, R> List<Class<R>> getTranscodeClasses(
@NonNull Class<Z> resourceClass, @NonNull Class<R> transcodeClass) {
List<Class<R>> transcodeClasses = new ArrayList<>();
//如果transcodeClass是resourceClass的父类(比如Drawable是BitmapDrawable和GifDrawable的父类)则为true。
//所以如果resourceClass传入的是Drawable的子类,则最终只会添加Drawable.class
if (transcodeClass.isAssignableFrom(resourceClass)) {
transcodeClasses.add(transcodeClass);
return transcodeClasses;
}
for (Entry<?, ?> entry : transcoders) {
if (entry.handles(resourceClass, transcodeClass)) {
//这里有效的是当传入Bitmap.class和Drawable.class的时候,所以最后会添加Drawable.calss
transcodeClasses.add(transcodeClass);
}
}
return transcodeClasses;
}
private static final class Entry<Z, R> {
private final Class<Z> fromClass;
private final Class<R> toClass;
@Synthetic
final ResourceTranscoder<Z, R> transcoder;
Entry(@NonNull Class<Z> fromClass, @NonNull Class<R> toClass,
@NonNull ResourceTranscoder<Z, R> transcoder) {
this.fromClass = fromClass;
this.toClass = toClass;
this.transcoder = transcoder;
}
public boolean handles(@NonNull Class<?> fromClass, @NonNull Class<?> toClass) {
return this.fromClass.isAssignableFrom(fromClass) && toClass.isAssignableFrom(this.toClass);
}
}
}
//Registry
public <TResource, Transcode> Registry register(
@NonNull Class<TResource> resourceClass, @NonNull Class<Transcode> transcodeClass,
@NonNull ResourceTranscoder<TResource, Transcode> transcoder) {
transcoderRegistry.register(resourceClass, transcodeClass, transcoder);
return this;
}
//Glide
Glide(){
registry
/* Transcoders */
.register(
Bitmap.class,
BitmapDrawable.class,
new BitmapDrawableTranscoder(resources))
}
getTransformation()
Transformation是一个接口,继承了Key接口,同时自己有一个transform方法,用来将Resource转换为另一个Resource。比如它的实现类CenterCrop,就是将Bitmap转为centerCrop样子的Bitmap。
getTransformation()则根据之前在transformations存好的键值对来获取Transformation。
<Z> Transformation<Z> getTransformation(Class<Z> resourceClass) {
Transformation<Z> result = (Transformation<Z>) transformations.get(resourceClass); //由BaseRequestOptions的transformations传递进来
if (result == null) {
for (Entry<Class<?>, Transformation<?>> entry : transformations.entrySet()) {
if (entry.getKey().isAssignableFrom(resourceClass)) {
result = (Transformation<Z>) entry.getValue();
break;
}
}
}
if (result == null) {
if (transformations.isEmpty() && isTransformationRequired) {
throw new IllegalArgumentException(
"Missing transformation for " + resourceClass + ". If you wish to"
+ " ignore unknown resource types, use the optional transformation methods.");
} else {
return UnitTransformation.get(); //这个默认返回原Resource,不做转换
}
}
return result;
}
在我们使用RequestBuilder显式调用centerCrop()或者其他转换时,最终会将对应的类型和Transformation存进transformations。如果没有显式调用,但是ImageView本身设置了转换的(比如设置了android:scaleType="centerCrop"),会在into()时进行设置存进transformations。
Glide.with(this)
.load("")
.centerCrop()
.into(imageView);
//BaseRequestOptions
public T centerCrop() {
return transform(DownsampleStrategy.CENTER_OUTSIDE, new CenterCrop());
}
final T transform(@NonNull DownsampleStrategy downsampleStrategy,
@NonNull Transformation<Bitmap> transformation) {
if (isAutoCloneEnabled) {
//在clone()中会设置isAutoCloneEnabled为false,所以最终还是会走到下面的语句
return clone().transform(downsampleStrategy, transformation);
}
downsample(downsampleStrategy);
return transform(transformation);
}
public T transform(@NonNull Transformation<Bitmap> transformation) {
return transform(transformation, /*isRequired=*/ true);
}
T transform(
@NonNull Transformation<Bitmap> transformation, boolean isRequired) {
if (isAutoCloneEnabled) {
return clone().transform(transformation, isRequired);
}
DrawableTransformation drawableTransformation =
new DrawableTransformation(transformation, isRequired);
//最终transformations添加的键值对为下面这些
transform(Bitmap.class, transformation, isRequired);
transform(Drawable.class, drawableTransformation, isRequired);
transform(BitmapDrawable.class, drawableTransformation.asBitmapDrawable(), isRequired);
transform(GifDrawable.class, new GifDrawableTransformation(transformation), isRequired);
return selfOrThrowIfLocked();
}
<Y> T transform(
@NonNull Class<Y> resourceClass,
@NonNull Transformation<Y> transformation,
boolean isRequired) {
if (isAutoCloneEnabled) {
return clone().transform(resourceClass, transformation, isRequired);
}
transformations.put(resourceClass, transformation); //在这里添加进去
fields |= TRANSFORMATION;
isTransformationAllowed = true;
fields |= TRANSFORMATION_ALLOWED;
// Always set to false here. Known scale only transformations will call this method and then
// set isScaleOnlyOrNoTransform to true immediately after.
isScaleOnlyOrNoTransform = false;
if (isRequired) {
fields |= TRANSFORMATION_REQUIRED;
isTransformationRequired = true;
}
return selfOrThrowIfLocked();
}
hasLoadPath()
LoadPath主要是封装了List<DecodePath<Data, ResourceType, Transcode>>,从而利用DecodePath根据给定的数据类型解码和转码资源类型。
在getLoadPath中首先从缓存中获取,如果没获取到则会继续获取decodePaths,如果decodePaths不为空,则创建一个新的LoadPath并传入缓存,最后返回。
//DecodeHelper
boolean hasLoadPath(Class<?> dataClass) {
return getLoadPath(dataClass) != null;
}
//Registry
<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)) {
//返回的是一个特定的LoadPath,代表之前没有发现可用的LoadPath。
//当下面的decodePaths.isEmpty()时,loadPathCache存入的result为null,这时实际存入的是一个特定的NO_PATHS_SIGNAL。
return null;
} else if (result == null) {
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;
}
//DecodePath则主是封装List<? extends ResourceDecoder<DataType, ResourceType>>和ResourceTranscoder<ResourceType, Transcode> transcoder来进行解码和转码工作
private <Data, TResource, Transcode> List<DecodePath<Data, TResource, Transcode>> getDecodePaths(
@NonNull Class<Data> dataClass/*InputStream.class*/, @NonNull Class<TResource> resourceClass/*Object.class*/,
@NonNull Class<Transcode> transcodeClass/*Drawable.class*/) {
List<DecodePath<Data, TResource, Transcode>> decodePaths = new ArrayList<>();
//这些getXXXClasses获取上面都有说过
List<Class<TResource>> registeredResourceClasses =
decoderRegistry.getResourceClasses(dataClass, resourceClass); //GifDrawable.class、Bitmap.class、BitmapDrawable.class
for (Class<TResource> registeredResourceClass : registeredResourceClasses) {
List<Class<Transcode>> registeredTranscodeClasses =
transcoderRegistry.getTranscodeClasses(registeredResourceClass, transcodeClass); //Drawable.class
for (Class<Transcode> registeredTranscodeClass : registeredTranscodeClasses) {
List<ResourceDecoder<Data, TResource>> decoders =
decoderRegistry.getDecoders(dataClass, registeredResourceClass); //StreamGifDecoder、BitmapDrawableDecoder
ResourceTranscoder<TResource, Transcode> transcoder =
transcoderRegistry.get(registeredResourceClass, registeredTranscodeClass); //BitmapDrawableTranscoder
@SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
DecodePath<Data, TResource, Transcode> path =
new DecodePath<>(dataClass/*InputStream.class*/, registeredResourceClass/*Bitmap.class*/, registeredTranscodeClass/*Drawable.class*/,
decoders/*StreamGifDecoder、BitmapDrawableDecoder*/, transcoder/*BitmapDrawableTranscoder*/, throwableListPool);
decodePaths.add(path);
}
}
return decodePaths;
}
getDiskCache()
获取磁盘缓存,具体请看Glide源码解析之DiskCache
DiskCache getDiskCache() {
return diskCacheProvider.getDiskCache();
}