Registry  Manages component registration to extend or replace Glide's default loading, decoding, and encoding logic.

它的主要工作是在Glide初始化的时候做的,我们截取一段代码看看

首先看看ModelLoader相关的

    registry.append(int.class, InputStream.class, resourceLoaderStreamFactory).append(int.class, ParcelFileDescriptor.class, resourceLoaderFileDescriptorFactory).append(Integer.class, InputStream.class, resourceLoaderStreamFactory).append(Integer.class, ParcelFileDescriptor.class, resourceLoaderFileDescriptorFactory).append(Integer.class, Uri.class, resourceLoaderUriFactory).append(int.class, AssetFileDescriptor.class, resourceLoaderAssetFileDescriptorFactory).append(Integer.class, AssetFileDescriptor.class, resourceLoaderAssetFileDescriptorFactory).append(int.class, Uri.class, resourceLoaderUriFactory).append(String.class, InputStream.class, new DataUrlLoader.StreamFactory<String>()).append(Uri.class, InputStream.class, new DataUrlLoader.StreamFactory<Uri>())//注意看modelClass 是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())

分析append方法:

  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;}

直接调用了ModeLoaderRegistry的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中封装了了一个MultiModelLoaderFactory,MultiModelLoaderFactory里面有一个List,append进来的都最终放到了这个list中,cache只是为了提高效率缓存。具体看ModelLoaderRegistry和MultiModelLoaderFactory源码,关键方法进行了注释。

Registry的append方法没什么难度,这个是放进去,那么我们怎么取出来了呢?

这个就是Registry的getModelLoaders方法,根据Model类型来获取一个ModelLoader的List。可以看ModelLoaderRegistry的源码,有注释。

  public <Model> List<ModelLoader<Model, ?>> getModelLoaders(@NonNull Model model) {return modelLoaderRegistry.getModelLoaders(model);}

ModelLoaderRegistry

package com.bumptech.glide.load.model;import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.util.Pools.Pool;
import com.bumptech.glide.Registry.NoModelLoaderAvailableException;
import com.bumptech.glide.util.Synthetic;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** Maintains an ordered put of {@link ModelLoader}s and the model and data types they handle in* order from highest priority to lowest.*/
// Hides Model throughout.
@SuppressWarnings("TypeParameterHidesVisibleType")
public class ModelLoaderRegistry {private final MultiModelLoaderFactory multiModelLoaderFactory;private final ModelLoaderCache cache = new ModelLoaderCache();public ModelLoaderRegistry(@NonNull Pool<List<Throwable>> throwableListPool) {this(new MultiModelLoaderFactory(throwableListPool));}private ModelLoaderRegistry(@NonNull MultiModelLoaderFactory multiModelLoaderFactory) {this.multiModelLoaderFactory = multiModelLoaderFactory;}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();}public synchronized <Model, Data> void prepend(@NonNull Class<Model> modelClass,@NonNull Class<Data> dataClass,@NonNull ModelLoaderFactory<? extends Model, ? extends Data> factory) {multiModelLoaderFactory.prepend(modelClass, dataClass, factory);cache.clear();}public synchronized <Model, Data> void remove(@NonNull Class<Model> modelClass, @NonNull Class<Data> dataClass) {tearDown(multiModelLoaderFactory.remove(modelClass, dataClass));cache.clear();}public synchronized <Model, Data> void replace(@NonNull Class<Model> modelClass,@NonNull Class<Data> dataClass,@NonNull ModelLoaderFactory<? extends Model, ? extends Data> factory) {tearDown(multiModelLoaderFactory.replace(modelClass, dataClass, factory));cache.clear();}private <Model, Data> void tearDown(@NonNull List<ModelLoaderFactory<? extends Model, ? extends Data>> factories) {for (ModelLoaderFactory<? extends Model, ? extends Data> factory : factories) {factory.teardown();}}// We're allocating in a loop to avoid allocating empty lists that will never have anything added// to them.@SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")@NonNullpublic <A> List<ModelLoader<A, ?>> getModelLoaders(@NonNull A model) {List<ModelLoader<A, ?>> modelLoaders = getModelLoadersForClass(getClass(model));if (modelLoaders.isEmpty()) {throw new NoModelLoaderAvailableException(model);}int size = modelLoaders.size();boolean isEmpty = true;List<ModelLoader<A, ?>> filteredLoaders = Collections.emptyList();/**下面这条注释的意思* https://stackoverflow.com/questions/17836373/what-does-noinspection-forloopreplaceablebyforeach-mean*///noinspection ForLoopReplaceableByForEach to improve perffor (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);}}if (filteredLoaders.isEmpty()) {throw new NoModelLoaderAvailableException(model, modelLoaders);}return filteredLoaders;}public synchronized <Model, Data> ModelLoader<Model, Data> build(@NonNull Class<Model> modelClass, @NonNull Class<Data> dataClass) {return multiModelLoaderFactory.build(modelClass, dataClass);}@NonNullpublic synchronized List<Class<?>> getDataClasses(@NonNull Class<?> modelClass) {return multiModelLoaderFactory.getDataClasses(modelClass);}@NonNullprivate synchronized <A> List<ModelLoader<A, ?>> getModelLoadersForClass(@NonNull Class<A> modelClass) {//这块又用到了缓存思想,如果没有新的modelClass添加,cache中的就是需要的//如果,不从缓存中取,就需要调用multiModelLoaderFactory的build,这样的化,就可能会实例化多个ModelLoader,开销会很大List<ModelLoader<A, ?>> loaders = cache.get(modelClass);if (loaders == null) {loaders = Collections.unmodifiableList(multiModelLoaderFactory.build(modelClass));cache.put(modelClass, loaders);}return loaders;}@NonNull@SuppressWarnings("unchecked")private static <A> Class<A> getClass(@NonNull A model) {return (Class<A>) model.getClass();}private static class ModelLoaderCache {private final Map<Class<?>, Entry<?>> cachedModelLoaders = new HashMap<>();@SyntheticModelLoaderCache() {}public void clear() {cachedModelLoaders.clear();}public <Model> void put(Class<Model> modelClass, List<ModelLoader<Model, ?>> loaders) {Entry<?> previous = cachedModelLoaders.put(modelClass, new Entry<>(loaders));if (previous != null) {throw new IllegalStateException("Already cached loaders for model: " + modelClass);}}@Nullable@SuppressWarnings("unchecked")public <Model> List<ModelLoader<Model, ?>> get(Class<Model> modelClass) {Entry<Model> entry = (Entry<Model>) cachedModelLoaders.get(modelClass);return entry == null ? null : entry.loaders;}private static class Entry<Model> {@Synthetic final List<ModelLoader<Model, ?>> loaders;public Entry(List<ModelLoader<Model, ?>> loaders) {this.loaders = loaders;}}}
}

MultiModelLoaderFactory是一个很重要的类,首先它存储了所有了modelClass、dataClass和ModelLoaderFactory的信息,在entries List里面。还有两个很重要的重载方法load。

synchronized <Model> List<ModelLoader<Model, ?>> build(@NonNull Class<Model> modelClass)

根据modelClass类型,把所有entries List中的所有modelClass类型的ModelLoader都通过工厂类ModelLoaderFactory方法build出来,并放到loaders List中返回。

需要说明的是不同的ModelLoaderFactory的build实现是不同的,build方法中传入的MultiModelLoaderFactory对象。

具体分析一个例子,我们看看StringLoader的工厂类,从类名我们也知道这个ModelLoader的modelClass是String,由于dataClass可以有很多种(InputStream、ParcelFileDescriptor、AssetFileDescriptor),所以也有很多种Factory,比如我们要分析的StreamFactory

  /** Factory for loading {@link InputStream}s from Strings. */public static class StreamFactory implements ModelLoaderFactory<String, InputStream> {@NonNull@Overridepublic ModelLoader<String, InputStream> build(@NonNull MultiModelLoaderFactory multiFactory) {return new StringLoader<>(multiFactory.build(Uri.class, InputStream.class));}@Overridepublic void teardown() {// Do nothing.}}

先看看StringLoader.StreamFactory的注册调用

.append(String.class, InputStream.class, new StringLoader.StreamFactory())

我们知道在MultiModelLoaderFactory的load方法中传入的是String.class,在迭代entries的时候,肯定会调用到StringLoader.StreamFactory的load方法,也就是上面的方法。重点来了

return new StringLoader<>(multiFactory.build(Uri.class, InputStream.class));

这里new一个StringLoader实例没有问题,问题是StringLoader里面包装了一个MutilModelLoader对象,而这个对象是由MultiModelLoaderFactory的重载的load方法返回的。

public synchronized <Model, Data> ModelLoader<Model, Data> build(@NonNull Class<Model> modelClass, @NonNull Class<Data> dataClass)

这个loader方法和上一个load主要逻辑是一致的,把modelClass和dataClass对应的ModelLoader通过Factory时候化出来,唯一区别是,把这些ModelLoader封装成一个MultiModelLoader,MultiModelLoader也是ModelLoader,它只是把modelClass相同,同时dataClass相同的ModelLoader封装到一个MultiModelLoader里面。

第一个build只有一个调用入口,ModelLoaderRegistry的getModelLoadersForClass方法,这是一个私有方法(这个方法里面加了一层缓存,看代码注释),被对外暴露的getModelLoaders方法调用,这个方法里面还需要进行一次校验,把无效的ModelLoader去掉。ModelLoaderRegistry的getModelLoaders方法被Registry的getModelLoaders方法调用。Registry的getModelLoaders就是业务逻辑中要用到的接口啦

下面我们以具体例子,调试分析一下

        ImageView glide_image_view = findViewById(R.id.glide_image_view);String str = "https://photocdn.tv.sohu.com/img/20161013/vrs_1476350821000_85454913_4wX29_pic6.jpg";Glide.with(this).load(str).into(glide_image_view);

从上面代码看,我们知道modelClass是String,这个也是我们最常用的方式

从DecodeHelper的getLoadData直接调用到MultiModelLoaderFactory的build(Class<Model> modelClass)方法

entries list里面存了所有注册进来的<modelClass, dataClass, factory>,有35个,我们要找到modelClass是String的,我们分析一个factory是StringLoader.StreamFactory的build,它会调用到MultiModelLoaderFactory 的build( @NonNull Class<Model> modelClass, @NonNull Class<Data> dataClass)

这个就是把modelClass是Uri,dataClass是InputStream,对应的所有ModelLoader包装成一个MultiModelLoader,然后再包装到StringLoader里面

看上图,这个loaders返回到ModelLoaderRegistry的getModelLoadersForClass方法进行缓存,在getModelLoaders中过滤无效的。是否有效通过ModelLoader的handle方法来判断的

DataUrlLoader的handle方法,返回fasle@Overridepublic boolean handles(@NonNull Model model) {// We expect Model to be a Uri or a String, both of which implement toString() efficiently. We// should reconsider this implementation before adding any new Model types.return model.toString().startsWith(DATA_SCHEME_IMAGE);}
//StringLoader 的handle方法返回true
@Overridepublic boolean handles(@NonNull String model) {// Avoid parsing the Uri twice and simply return null from buildLoadData if we don't handle this// particular Uri type.return true;}

我们接着看看DecodeHelper的getLoadData方法

  List<LoadData<?>> getLoadData() {if (!isLoadDataSet) {isLoadDataSet = true;loadData.clear();List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model);//noinspection ForLoopReplaceableByForEach to improve perffor (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;}

 glideContext.getRegistry().getModelLoaders(model)上面已经分析过了,就是根据model的类型(比如String)获取一个能处理model类型的ModelLoader的列表。ModelLoader是一个工厂接口,它能把任意的数据model转化成DataFetcher能使用具体数据类型,通过buildLoadData方法完成,看个例子

我们现在知道modelLoaders的size是3,get(0)是个StringLoader,里面封装了7个loader,StringLoader是个MultiModelLoader,看看它的buildLoadData方法

  @Overridepublic LoadData<Data> buildLoadData(@NonNull Model model, int width, int height,@NonNull Options options) {Key sourceKey = null;int size = modelLoaders.size();List<DataFetcher<Data>> fetchers = new ArrayList<>(size);//noinspection ForLoopReplaceableByForEach to improve perffor (int i = 0; i < size; i++) {ModelLoader<Model, Data> modelLoader = modelLoaders.get(i);if (modelLoader.handles(model)) {LoadData<Data> loadData = modelLoader.buildLoadData(model, width, height, options);if (loadData != null) {sourceKey = loadData.sourceKey;fetchers.add(loadData.fetcher);}}}return !fetchers.isEmpty() && sourceKey != null? new LoadData<>(sourceKey, new MultiFetcher<>(fetchers, exceptionListPool)) : null;}

很简单,就是把7个loader遍历一遍,求得的LoadData们,组装成一个新的LoadData,我们知道七个中有一个是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);
}

这个urlLoader是HttpGlideUrlLoader

@Override
public LoadData<InputStream> buildLoadData(@NonNull GlideUrl model, int width, int height, @NonNull Options options) {// GlideUrls memoize parsed URLs so caching them saves a few object instantiations and time// spent parsing urls.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));
}

看到没,通过一系列的调用下来,model是String类型,被转换成了GlideUrl类型,这个类型是被HttpUrlFetcher使用的,统一被封装到了LoadData里面。现在再来体会一些对ModelLoader的解释。

如下图

看到没这个loadData中是一个MultiFetcher 里面有两HttpUrlFetcher

get(1)和get(2)的StringLoader都不会生成LoadData。

总结一下,getLoadData返回的loadData list中只有一个LoadData实例,sourceKey是地址封装成的GlideUrl,fetcher是个MultiFetcher包含了两个HttpUrlFetcher。

看看DecodeHelper 的getCacheKeys方法

  List<Key> getCacheKeys() {if (!isCacheKeysSet) {isCacheKeysSet = true;cacheKeys.clear();List<LoadData<?>> loadData = getLoadData();//noinspection ForLoopReplaceableByForEach to improve perffor (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里面

MultiModelLoaderFactory

package com.bumptech.glide.load.model;import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.core.util.Pools.Pool;
import com.bumptech.glide.Registry.NoModelLoaderAvailableException;
import com.bumptech.glide.load.Options;
import com.bumptech.glide.util.Preconditions;
import com.bumptech.glide.util.Synthetic;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;/*** Capable of building an {@link ModelLoader} that wraps one or more other {@link ModelLoader}s for* a given model and data class.*/
// Hides Model throughout.
@SuppressWarnings("TypeParameterHidesVisibleType")
public class MultiModelLoaderFactory {private static final Factory DEFAULT_FACTORY = new Factory();private static final ModelLoader<Object, Object> EMPTY_MODEL_LOADER = new EmptyModelLoader();private final List<Entry<?, ?>> entries = new ArrayList<>();private final Factory factory;private final Set<Entry<?, ?>> alreadyUsedEntries = new HashSet<>();private final Pool<List<Throwable>> throwableListPool;public MultiModelLoaderFactory(@NonNull Pool<List<Throwable>> throwableListPool) {this(throwableListPool, DEFAULT_FACTORY);}@VisibleForTestingMultiModelLoaderFactory(@NonNull Pool<List<Throwable>> throwableListPool, @NonNull Factory factory) {this.throwableListPool = throwableListPool;this.factory = factory;}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);}synchronized <Model, Data> void prepend(@NonNull Class<Model> modelClass,@NonNull Class<Data> dataClass,@NonNull ModelLoaderFactory<? extends Model, ? extends Data> factory) {add(modelClass, dataClass, factory, /*append=*/ false);}/** 不同类型的modelClass、dataClass和ModeLoaderFactory都会被打包成Entry放到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);}@NonNullsynchronized <Model, Data> List<ModelLoaderFactory<? extends Model, ? extends Data>> replace(@NonNull Class<Model> modelClass,@NonNull Class<Data> dataClass,@NonNull ModelLoaderFactory<? extends Model, ? extends Data> factory) {List<ModelLoaderFactory<? extends Model, ? extends Data>> removed =remove(modelClass, dataClass);append(modelClass, dataClass, factory);return removed;}@NonNullsynchronized <Model, Data> List<ModelLoaderFactory<? extends Model, ? extends Data>> remove(@NonNull Class<Model> modelClass, @NonNull Class<Data> dataClass) {List<ModelLoaderFactory<? extends Model, ? extends Data>> factories = new ArrayList<>();for (Iterator<Entry<?, ?>> iterator = entries.iterator(); iterator.hasNext(); ) {Entry<?, ?> entry = iterator.next();if (entry.handles(modelClass, dataClass)) {iterator.remove();factories.add(this.<Model, Data>getFactory(entry));}}return factories;}/*** 根据modelClass类型,把所有entries List中的所有modelClass类型的ModelLoader都通过工厂方法build出来,* 并放到loaders List中返回*/@NonNullsynchronized <Model> List<ModelLoader<Model, ?>> build(@NonNull Class<Model> modelClass) {try {List<ModelLoader<Model, ?>> loaders = new ArrayList<>();for (Entry<?, ?> entry : entries) {// Avoid stack overflow recursively creating model loaders by only creating loaders in// recursive requests if they haven't been created earlier in the chain. For example:// A Uri loader may translate to another model, which in turn may translate back to a Uri.// The original Uri loader won't be provided to the intermediate model loader, although// other Uri loaders will be.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;}}@NonNullsynchronized 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;}/*** 根据modelClass类型和dataClass类型,把所有entries List中的所有modelClass类型同时是dataClasse类型的ModelLoader都通过工厂方法build出来,* 并放到loaders List中,如果List size大于1,构造一个MultiModelLoader,并返回** 这个引入了MultiModelLoader,它也是一个ModelLoader,只是封装了多个ModelLoader。也就是为啥这个类叫MultiModelLoaderFactory*/@NonNullpublic 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) {// Avoid stack overflow recursively creating model loaders by only creating loaders in// recursive requests if they haven't been created earlier in the chain. For example:// A Uri loader may translate to another model, which in turn may translate back to a Uri.// The original Uri loader won't be provided to the intermediate model loader, although// other Uri loaders will be.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 {// Avoid crashing if recursion results in no loaders available. The assertion is supposed to// catch completely unhandled types, recursion may mean a subtype isn't handled somewhere// down the stack, which is often ok.if (ignoredAnyEntries) {return emptyModelLoader();} else {throw new NoModelLoaderAvailableException(modelClass, dataClass);}}} catch (Throwable t) {alreadyUsedEntries.clear();throw t;}}@NonNull@SuppressWarnings("unchecked")private <Model, Data> ModelLoaderFactory<Model, Data> getFactory(@NonNull Entry<?, ?> entry) {return (ModelLoaderFactory<Model, Data>) entry.factory;}@NonNull@SuppressWarnings("unchecked")private <Model, Data> ModelLoader<Model, Data> build(@NonNull Entry<?, ?> entry) {return (ModelLoader<Model, Data>) Preconditions.checkNotNull(entry.factory.build(this));}@NonNull@SuppressWarnings("unchecked")private static <Model, Data> ModelLoader<Model, Data> emptyModelLoader() {return (ModelLoader<Model, Data>) EMPTY_MODEL_LOADER;}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, @NonNull Class<?> dataClass) {return handles(modelClass) && this.dataClass.isAssignableFrom(dataClass);}public boolean handles(@NonNull Class<?> modelClass) {return this.modelClass.isAssignableFrom(modelClass);}}static class Factory {@NonNullpublic <Model, Data> MultiModelLoader<Model, Data> build(@NonNull List<ModelLoader<Model, Data>> modelLoaders,@NonNull Pool<List<Throwable>> throwableListPool) {return new MultiModelLoader<>(modelLoaders, throwableListPool);}}private static class EmptyModelLoader implements ModelLoader<Object, Object> {@SyntheticEmptyModelLoader() {}@Nullable@Overridepublic LoadData<Object> buildLoadData(@NonNull Object o, int width, int height, @NonNull Options options) {return null;}@Overridepublic boolean handles(@NonNull Object o) {return false;}}
}

分析一下ModelLoader相关的代码

ModelLoader是一个工厂接口,HttpGlideUrlLoader是其中实现的一个子类,对这个子类进行分析

glide里面好多对象都是通过工厂类或者接口创建处理的,这种设计模式和采用原因,以后分析

  /*** The default factory for {@link HttpGlideUrlLoader}s.*/public static class Factory implements ModelLoaderFactory<GlideUrl, InputStream> {private final ModelCache<GlideUrl, GlideUrl> modelCache = new ModelCache<>(500);@NonNull@Overridepublic ModelLoader<GlideUrl, InputStream> build(MultiModelLoaderFactory multiFactory) {return new HttpGlideUrlLoader(modelCache);}@Overridepublic void teardown() {// Do nothing.}}

通过一个工厂类,创建一个HttpGlideUrlLoader对象,需要传入一个ModelCache对象,分析一个这个ModelCache类

ModelCache里面封装了LruCache(需要研读LruCache代码),LruCache采用最近最少使用算法,存放key-value。在ModelCache中,key是ModelKey(ModelKey是ModelCache的嵌套类),ModelKey就是存了model、width和height而已,在HttpGlideUrlLoader中model的类型是GlideUrl,value类型也是GlideUrl。

我们可以直观的感受到ModelCache对外暴露的接口功能是从LruCache中存取,实际也是如此:

/*** Add a value.** @param model  The model.* @param width  The width in pixels of the view the image is being loaded into.* @param height The height in pixels of the view the image is being loaded into.* @param value  The value to store.*/public void put(A model, int width, int height, B value) {ModelKey<A> key = ModelKey.get(model, width, height);cache.put(key, value);}/*** Get a value.** @param model  The model.* @param width  The width in pixels of the view the image is being loaded into.* @param height The height in pixels of the view the image is being loaded into.* @return The cached result, or null.*/@Nullablepublic B get(A model, int width, int height) {ModelKey<A> key = ModelKey.get(model, width, height);B result = cache.get(key);key.release();return result;}

我们思考一个问题:在我们实际开发中,从Map中存取的话,key一般是什么类型的?答案是不是String比较多。

可是我们看看上面分析的代码,key是什么?key是一个自己定义的类ModelKey,一个复杂的对象。

如果key是String的话,我们潜意识的就是知道只要内容一样,key就一样,就能在map中存取了,这个其实是String重写的hashCode和equals方法保证的。

现在的问题是,我们的key是自定义的ModelKey类型,为了能保证我们new的key对象和Map中的key对象相等,我们也需要重写ModelKey的hashCode和equals方法。看看ModelKey的源码确实是这样。

java基础 equals和hashCode、HashMap

还有另外一个问题:我们map(LruCache)中通过key存取时,每次是不是都得new ModelKey实例呢?创建对象是很消耗性能的,Glide对此做了优化,其实说来也简单,就是做个对象池,把用过的对象key缓存起来,这样的话需要key的话,就从这个对象池中取,把里面的内容改一下就行了。LruCache采用LRU算法,在清理的时候,把key保存到对象池中。对象池的实现方案很多,可以采用Queue也可是采用链表List,在这里采用了Queue,在ModelKey维护了一个静态Queue用作对象池。

现在再看ModelCache的get和set方法就明白了呢?ModelKey<A> key = ModelKey.get(model, width, height);是从对象池中取key,key.release();是把这个key对象放到对象池中。

现在ModelCache分析完了,该回到主线HttpGlideUrlLoader类了,它实现了ModelLoader接口,这个接口里面定义了一个LoadData的数据结构,通过buildLoadData方法把任意复杂的数据类型,比如Url、File,转换成包装后的LoadData,同时这个LoadData对象中还包含了DataFetcher对象。

我们再分析一下DataFetcher

DataFetcher中loadData方法去真正请求数据,HttpUrlFetcher中是通过HttpURLConnection去获取网络数据的。

Glide4.8源码拆解(三)Registry和数据转换流程

数据加载DataFetcher与ModelLoader结构

java.util.Collections类——emptyList()方法

MessageDigest来实现数据加密

Android Bitmap(位图)详解

Bitmap和Drawable的关系、区别

Glide 之 Registry、ModelLoaderRegistry、 MultiModelLoaderFactory、 ModelLoader 分析相关推荐

  1. Android 图片框架原理——Glide源码分析

    目录 前言 一.With() 二.load() 三.into() 1. buildImageViewTarget() 2.关注1 :buildRequest 构建 3.关注2:runRequest 执 ...

  2. Glide系列(四) — Glide缓存流程分析

    文章目录 一.概述 1.1 背景 1.2 系列文章 二.准备知识 2.1 Glide 的缓存分层结构 2.2 Glide 缓存相关类的关联关系 三.缓存的获取流程 3.1 缓存获取的入口 3.2 内存 ...

  3. Android Glide图片加载框架(二)源码解析之into()

    文章目录 一.前言 二.源码解析 1.into(ImageView) 2.GlideContext.buildImageViewTarget() 3.RequestBuilder.into(Targe ...

  4. Android图片加载框架——Glide(Glide v4)

    原文地址 Android图片加载框架--Glide(Glide v4) 前言 android中图片加载框架有很多,所有框架最终达到的目都是在Android平台上以极度简单的方式加载和展示图片,如果我们 ...

  5. Glide 4.9源码解析-图片加载流程

    本文Glide源码基于4.9,版本下载地址如下:Glide 4.9 前言 由于Glide源码真的很复杂,因此本文只分析和贴出与图片加载流程相关的功能以及代码.另外本文Glide源码基于4.9,与3.x ...

  6. 你真的会使用Glide吗?——Glide的高级用法

    今天给大家分享一下Glide的一些使用技巧.Glide应该是Android APP中使用最为广泛的图片加载框架了,如丝般的顺滑滚动以及方便的链式调用为广大开发者所喜爱.但是开发中,我们总能遇上一些不太 ...

  7. Glide 4.9源码解析-缓存策略

    本文Glide源码基于4.9,版本下载地址如下:Glide 4.9 前言 在分析了Glide的图片加载流程后,更加发觉到Glide的强大,于是这篇文章将继续深入分析Glide的缓存策略.不过今天的文章 ...

  8. Android图片加载框架最全解析(二),从源码的角度理解Glide的执行流程

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/53939176 本文同步发表于我的微信公众号,扫一扫文章底部的二维码或在微信搜索 郭 ...

  9. Android图片加载框架最全解析(三),深入探究Glide的缓存机制

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/54895665 本文同步发表于我的微信公众号,扫一扫文章底部的二维码或在微信搜索 郭 ...

最新文章

  1. 数据库缓存最终一致性的四种方案
  2. 列表自定义的Type和BaseType参考
  3. 【解题报告】【HDOJ1392】【Graham凸包】Surround the Trees
  4. docker运行prometheus
  5. C#并行编程(3):并行循环
  6. 正确获取Java事件通知
  7. 让VS2013支持 C# 6.0 语法
  8. ES6函数参数的解构赋值,以及2种设置参数默认值方法的区别
  9. Linux的学习笔记~
  10. python背单词小程序_python背单词小程序
  11. 三阶魔方还原步骤图_五阶魔方还原教程——层先法
  12. Linux系统和UNIX系统简介
  13. picsart旧版本_picsart 2016旧版本下载-picsart 2016版本下载v5.25.4 安卓中文版-2265安卓网...
  14. 【WPS表格】快捷键合集(更新中)
  15. 国家开放大学2021春1315社会调查方法题目
  16. CSS盒子模型、Boder基础
  17. WLAN从入门到精通-1
  18. 三种T检验之间的区别
  19. monocle安装不成功 想尽各种办法
  20. 最好用的 20 款数据可视化工具

热门文章

  1. python通讯录编程_python实现简单通讯录
  2. 如何通过通达信接口获取最近的分钟级别行情数据?
  3. 使用LabVIEW 开发远程电子工程实验课
  4. python调用mysql数据库sql语句过长有问题吗_Python 连接Mysql数据库执行sql语句
  5. ChatGPT在安全研究领域的应用实践
  6. Linux环境下如何让可执行文件在shell中执行
  7. 数据结构 | 堆的向上调整和向下调整算法【奇妙的堆排序】
  8. 国产芯片----瑞盟MS258低功耗通用型运放,兼容替代LM258
  9. 2020 ccpc 吉林省赛 H
  10. OpenAL播放器使用