The code is as follows:

private <T> DrawableTypeRequest<T> loadGeneric(Class<T> modelClass) { //1. Get streamModelLoader ModelLoader < T, InputStream > streamModelLoader = Glide. BuildStreamModelLoader (modelClass, context); / / 2. Obtain fileDescriptorModelLoader ModelLoader < T, ParcelFileDescriptor> fileDescriptorModelLoader = Glide.buildFileDescriptorModelLoader(modelClass, context); if (modelClass ! = null && streamModelLoader == null && fileDescriptorModelLoader == null) { throw new IllegalArgumentException("Unknown type " + modelClass + ". You must provide a Model of a type for" + " which there is a registered ModelLoader, if you are using a custom model, you must first call" + " Glide#register with a ModelLoaderFactory for your custom model class"); DrawableTypeRequest return optionsapplier. apply(new DrawableTypeRequest<T>(modelClass, streamModelLoader, fileDescriptorModelLoader, context, glide, requestTracker, lifecycle, optionsApplier)); } public DrawableTypeRequest<String> load(String string) { //4. load return (DrawableTypeRequest<String>) fromString().load(string); } public DrawableTypeRequest<String> fromString() { return loadGeneric(String.class); }Copy the code

The flow chart is as follows:




RequestManager.load

  1. buildModelLoader: On requestmodelAnd what needs to be resolvedmodelGet the correspondingModelLoader
  • Glide.buildModelLoader()
public static <T, Y> ModelLoader<T, Y> buildModelLoader(Class<T> modelClass, Class<Y> resourceClass, Context context) { if (modelClass == null) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Unable to load null model, setting placeholder only"); } return null; } // see [1.1] Glide. Get see [1.2] buildModelLoader return Glide. Get (context).getLoaderFactory().buildModelLoader(modelClass,  resourceClass); }Copy the code
  • 1.1
    • Glide. The get () :moduleConfiguration resolution, initializationGlideobject
public static Glide get(Context context) { if (glide == null) { synchronized (Glide.class) { if (glide == null) { Context applicationContext = context.getApplicationContext(); [1.1.1] List<GlideModule> modules = new ManifestParser(applicationContext).parse(); GlideBuilder builder = new GlideBuilder(applicationContext); For (GlideModule Module: modules) {module.applyOptions(applicationContext, Builder); } // See [1.1.2] Glide = builder.createglide (); / / traverse module, complete registration for (GlideModule module: modules) {module. RegisterComponents (applicationContext, glide); } } } } return glide; }Copy the code
  • 1.1.1
    • ManifestParser. Parser () : parsingAndroidManifest.xmlConfiguration of themodule
public List<GlideModule> parse() { List<GlideModule> modules = new ArrayList<GlideModule>(); try { ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo( context.getPackageName(), PackageManager.GET_META_DATA); if (appInfo.metaData ! = null) { for (String key : appInfo.metaData.keySet()) { if (GLIDE_MODULE_VALUE.equals(appInfo.metaData.get(key))) { modules.add(parseModule(key)); } } } } catch (PackageManager.NameNotFoundException e) { throw new RuntimeException("Unable to find metadata to parse GlideModules", e); } return modules; } private static GlideModule parseModule(String className) { Class<? > clazz; try { clazz = Class.forName(className); } catch (ClassNotFoundException e) { throw new IllegalArgumentException("Unable to find GlideModule implementation", e);  } Object module; Try {// Initialize module module = clazz.newinstance (); } catch (InstantiationException e) { throw new RuntimeException("Unable to instantiate GlideModule implementation for " + clazz, e); } catch (IllegalAccessException e) { throw new RuntimeException("Unable to instantiate GlideModule implementation for " + clazz, e); } if (! (module instanceof GlideModule)) { throw new RuntimeException("Expected instanceof GlideModule, but found: " + module); } return (GlideModule) module; }Copy the code
  • 1.1.2
    • GlideBuilder.createGlide():GlideInitialize the
Glide createGlide() {if (sourceService == null) {final int cores = math.max (1, 1) Runtime.getRuntime().availableProcessors()); / / has the priority order of thread pool sourceService = new FifoPriorityThreadPoolExecutor (cores); } if (diskCacheService == null) { diskCacheService = new FifoPriorityThreadPoolExecutor(1); } // MemorySizeCalculator calculator = new MemorySizeCalculator(context); if (bitmapPool == null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { int size = calculator.getBitmapPoolSize(); // bitmapPool = new LruBitmapPool(size); } else { bitmapPool = new BitmapPoolAdapter(); }} / / memory cache if (memoryCache = = null) {memoryCache = new LruResourceCache (calculator. GetMemoryCacheSize ()); } / / disk cache if (diskCacheFactory = = null) {diskCacheFactory = new InternalCacheDiskCacheFactory (context); If (engine == null) {engine = new engine (memoryCache, diskCacheFactory, diskCacheService, sourceService); // PREFER_RGB_565 decodeFormat = decodeformat.default; // PREFER_RGB_565 decodeFormat = decodeformat.default; } return new Glide(engine, memoryCache, bitmapPool, context, decodeFormat); } Glide(Engine engine, MemoryCache memoryCache, BitmapPool bitmapPool, Context context, DecodeFormat decodeFormat) { this.engine = engine; this.bitmapPool = bitmapPool; this.memoryCache = memoryCache; this.decodeFormat = decodeFormat; //ModelLoader generates factory class loaderFactory = new GenericLoaderFactory(context); mainHandler = new Handler(Looper.getMainLooper()); bitmapPreFiller = new BitmapPreFiller(memoryCache, bitmapPool, decodeFormat); / / register DataLoadProviderRegistry DataLoadProviderRegistry = new DataLoadProviderRegistry (); StreamBitmapDataLoadProvider streamBitmapLoadProvider = new StreamBitmapDataLoadProvider(bitmapPool, decodeFormat); dataLoadProviderRegistry.register(InputStream.class, Bitmap.class, streamBitmapLoadProvider); FileDescriptorBitmapDataLoadProvider fileDescriptorLoadProvider = new FileDescriptorBitmapDataLoadProvider(bitmapPool, decodeFormat); dataLoadProviderRegistry.register(ParcelFileDescriptor.class, Bitmap.class, fileDescriptorLoadProvider); ImageVideoDataLoadProvider imageVideoDataLoadProvider = new ImageVideoDataLoadProvider(streamBitmapLoadProvider, fileDescriptorLoadProvider); dataLoadProviderRegistry.register(ImageVideoWrapper.class, Bitmap.class, imageVideoDataLoadProvider); GifDrawableLoadProvider gifDrawableLoadProvider = new GifDrawableLoadProvider(context, bitmapPool); dataLoadProviderRegistry.register(InputStream.class, GifDrawable.class, gifDrawableLoadProvider); dataLoadProviderRegistry.register(ImageVideoWrapper.class, GifBitmapWrapper.class, new ImageVideoGifDrawableLoadProvider(imageVideoDataLoadProvider, gifDrawableLoadProvider, bitmapPool)); dataLoadProviderRegistry.register(InputStream.class, File.class, new StreamFileDataLoadProvider()); / / GenericLoaderFactory register register (File. Class, ParcelFileDescriptor. Class, new FileDescriptorFileLoader. The Factory ()); register(File.class, InputStream.class, new StreamFileLoader.Factory()); register(int.class, ParcelFileDescriptor.class, new FileDescriptorResourceLoader.Factory()); register(int.class, InputStream.class, new StreamResourceLoader.Factory()); register(Integer.class, ParcelFileDescriptor.class, new FileDescriptorResourceLoader.Factory()); register(Integer.class, InputStream.class, new StreamResourceLoader.Factory()); register(String.class, ParcelFileDescriptor.class, new FileDescriptorStringLoader.Factory()); register(String.class, InputStream.class, new StreamStringLoader.Factory()); register(Uri.class, ParcelFileDescriptor.class, new FileDescriptorUriLoader.Factory()); register(Uri.class, InputStream.class, new StreamUriLoader.Factory()); register(URL.class, InputStream.class, new StreamUrlLoader.Factory()); register(GlideUrl.class, InputStream.class, new HttpUrlGlideUrlLoader.Factory()); register(byte[].class, InputStream.class, new StreamByteArrayLoader.Factory()); / / register TranscoderRegistry TranscoderRegistry. Register (Bitmap. Class, GlideBitmapDrawable. Class, new GlideBitmapDrawableTranscoder(context.getResources(), bitmapPool)); transcoderRegistry.register(GifBitmapWrapper.class, GlideDrawable.class, new GifBitmapWrapperDrawableTranscoder( new GlideBitmapDrawableTranscoder(context.getResources(), bitmapPool))); bitmapCenterCrop = new CenterCrop(bitmapPool); drawableCenterCrop = new GifBitmapWrapperTransformation(bitmapPool, bitmapCenterCrop); bitmapFitCenter = new FitCenter(bitmapPool); drawableFitCenter = new GifBitmapWrapperTransformation(bitmapPool, bitmapFitCenter); } // According to modelClass, resourceClass, GenericLoaderFactory public <T, Y> void register(Class<T> modelClass, Class<Y> resourceClass, ModelLoaderFactory<T, Y> factory) {// see [1.1.3] ModelLoaderFactory<T, Y> removed = loaderFactory.register(modelClass, resourceClass, factory); if (removed ! = null) { removed.teardown(); }}Copy the code

As you can see, Glide does a lot of work when it initializes cache-related classes, task execution and cache management engines, registers DataLoadProviderRegistry GenericLoaderFactory, and so on. Glide.get(Context).getLoaderFactory() is GenericLoaderFactory

  • 1.1.3
    • GenericLoaderFactory.register()
public synchronized <T, Y> ModelLoaderFactory<T, Y> register(Class<T> modelClass, Class<Y> resourceClass, ModelLoaderFactory<T, Y> factory) { cachedModelLoaders.clear(); / / modelClassToResourceFactories key for modelClass, value is already resourceClass is key, Factory <Class/*Y*/, ModelLoaderFactory/*T, Y*/> resourceToFactories = modelClassToResourceFactories.get(modelClass); if (resourceToFactories == null) { resourceToFactories = new HashMap<Class/*Y*/, ModelLoaderFactory/*T, Y*/>(); modelClassToResourceFactories.put(modelClass, resourceToFactories); } ModelLoaderFactory/*T, Y*/ previous = resourceToFactories.put(resourceClass, factory); if (previous ! = null) { // This factory may be being used by another model. We don't want to say it has been removed unless we // know  it has been removed for all models. for (Map<Class/*Y*/, ModelLoaderFactory/*T, Y*/> factories : modelClassToResourceFactories.values()) { if (factories.containsValue(previous)) { previous = null; break; } } } return previous; }Copy the code
  • 1.2
    • GenericLoaderFactory.buildModelLoader()
public synchronized <T, Y> ModelLoader<T, Y> buildModelLoader(Class<T> modelClass, Class<Y> resourceClass) {// Get the cached ModelLoader ModelLoader<T, Y> result = getCachedLoader(modelClass, resourceClass); if (result ! = null) { // We've already tried to create a model loader and can't with the currently registered set of factories, // but we can't use null to demonstrate that failure because model loaders that haven't been requested // yet will be null in the cache. To avoid this, we use a special signal model loader. if (NULL_MODEL_LOADER.equals(result)) { return null; } else { return result; }} // Obtain the corresponding ModelLoaderFactory according to modelClass and resourceClass final ModelLoaderFactory<T, Y> factory = getFactory(modelClass, resourceClass); if (factory ! [1.2.1] result = factory.build(context, this); cacheModelLoader(modelClass, resourceClass, result); } else { // We can't generate a model loader for the given arguments with the currently registered set of factories. cacheNullLoader(modelClass, resourceClass); } return result; } private <T, Y> ModelLoaderFactory<T, Y> getFactory(Class<T> modelClass, Class < Y > resourceClass) {/ / at the time of Glide initialization 1.1.2 】 【 modelClassToResourceFactories registered correspondence Map < Class / * * / Y, ModelLoaderFactory/*T, Y*/> resourceToFactories = modelClassToResourceFactories.get(modelClass); ModelLoaderFactory/*T, Y*/ result = null; if (resourceToFactories ! = null) { result = resourceToFactories.get(resourceClass); } if (result == null) { for (Class<? super T> registeredModelClass : modelClassToResourceFactories.keySet()) { // This accounts for model subclasses, our map only works for exact matches. We should however still // match a subclass of a model with a factory for a super class of that model if if there isn't a // factory for that particular subclass. Uris are a great example of when this happens, most uris // are actually subclasses for Uri, but we'd generally rather load them all with the same factory rather // than trying to register for each subclass individually. if (registeredModelClass.isAssignableFrom(modelClass)) { Map<Class/*Y*/, ModelLoaderFactory/*T, Y*/> currentResourceToFactories = modelClassToResourceFactories.get(registeredModelClass); if (currentResourceToFactories ! = null) { result = currentResourceToFactories.get(resourceClass); if (result ! = null) { break; } } } } } return result; }Copy the code
  • 1.2.1
    • Factory. The build () : according toModelLoaderFactoryAccess to theModelLoaderHere, usemodule.class=String.classFor example, [1.1.2] Glide is known when it is initializedregister(String.class, InputStream.class, new StreamStringLoader.Factory());
    • StreamStringLoader.Factory.build()
public class StreamStringLoader extends StringLoader<InputStream> implements StreamModelLoader<String> { /** * The default factory for {@link com.bumptech.glide.load.model.stream.StreamStringLoader}s. */ public static class Factory implements ModelLoaderFactory<String, InputStream> { @Override public ModelLoader<String, InputStream> build(Context context, GenericLoaderFactory factories) {/ / here through ` factories. BuildModelLoader ` to build a ` module. The class = Uri. The class ` types of ` ModuleLoader `, Register (uri. class, inputStream. class, new StreamUriloader.factory ()); `. ` factories. BuildModelLoader ` see [1.2] return new StreamStringLoader (factories. BuildModelLoader (Uri) class, InputStream.class)); } @Override public void teardown() { // Do nothing. } } public StreamStringLoader(Context context) { this(Glide.buildStreamModelLoader(Uri.class, context)); } public StreamStringLoader(ModelLoader<Uri, InputStream> uriLoader) { super(uriLoader); } } public class StreamUriLoader extends UriLoader<InputStream> implements StreamModelLoader<Uri> { /** * THe default factory for {@link com.bumptech.glide.load.model.stream.StreamUriLoader}s. */ public static class Factory implements ModelLoaderFactory<Uri, InputStream> { @Override public ModelLoader<Uri, InputStream> build(Context context, GenericLoaderFactory Factories) {// [1.1.2] register(glideurl.class, inputStream.class, new HttpUrlGlideUrlLoader.Factory()); return new StreamUriLoader(context, factories.buildModelLoader(GlideUrl.class, InputStream.class)); } @Override public void teardown() { // Do nothing. } } public StreamUriLoader(Context context) { this(context, Glide.buildStreamModelLoader(GlideUrl.class, context)); } public StreamUriLoader(Context context, ModelLoader<GlideUrl, InputStream> urlLoader) { super(context, urlLoader); } / /... } public class HttpUrlGlideUrlLoader implements ModelLoader<GlideUrl, InputStream> { private final ModelCache<GlideUrl, GlideUrl> modelCache; /** * The default factory for {@link com.bumptech.glide.load.model.stream.HttpUrlGlideUrlLoader}s. */ public static class Factory implements ModelLoaderFactory<GlideUrl, InputStream> { private final ModelCache<GlideUrl, GlideUrl> modelCache = new ModelCache<GlideUrl, GlideUrl>(500); @Override public ModelLoader<GlideUrl, InputStream> build(Context context, GenericLoaderFactory factories) { return new HttpUrlGlideUrlLoader(modelCache); } @Override public void teardown() { // Do nothing. } } public HttpUrlGlideUrlLoader() { this(null); } public HttpUrlGlideUrlLoader(ModelCache<GlideUrl, GlideUrl> modelCache) { this.modelCache = modelCache; } @Override public DataFetcher<InputStream> getResourceFetcher(GlideUrl model, int width, int height) { // 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; } } return new HttpUrlFetcher(url); }}Copy the code

StreamStringLoader inherit StringLoader StringLoader has a ModelLoader uriLoader member variables, when the build, Here by factories. BuildModelLoader to build a module, class = Uri. The ModuleLoader of class type, Register (uri.class, inputStream.class, new StreamUriloader.factory ()); StreamUriLoader inherits UriLoader, which has a ModelLoader urlLoader member variable, This time also by factories. BuildModelLoader to the module. Class = GlideUrl. Access to the class, the register 1.1.2 】 【 (GlideUrl. Class, InputStream. Class, new HttpUrlGlideUrlLoader.Factory()); The layer by layer acquisition here is very clever.

  1. Glide.buildFileDescriptorModelLoader: getfileDescriptorModelLoader
public static <T> ModelLoader<T, ParcelFileDescriptor> buildFileDescriptorModelLoader(Class<T> modelClass, The Context Context) {/ / see [1] return buildModelLoader (modelClass, ParcelFileDescriptor. Class, Context); }Copy the code

Module. Class = String. Class = String. register(String.class, ParcelFileDescriptor.class, new FileDescriptorStringLoader.Factory()); Similar to [1.2.1], it is also a layer by layer acquisition, which is not nonsense.

  1. Get DrawableTypeRequest: DrawableTypeRequesT inheritanceDrawableRequestBuilder.DrawableRequestBuilderinheritanceGenericRequestBuilder
private final OptionsApplier optionsApplier; this.optionsApplier = new OptionsApplier(); //【3.1】 new DrawableTypeRequest optionsapplier. apply(new DrawableTypeRequest<T>(modelClass, streamModelLoader, fileDescriptorModelLoader, context, glide, requestTracker, lifecycle, optionsApplier)) class OptionsApplier { public <A, X extends GenericRequestBuilder<A, ? ,? ,? >> X apply(X builder) { //HOOK if (options ! = null) { options.apply(builder); } return builder; }}Copy the code

When we get the Request object, we leave a hook.

  • 3.1
    • new DrawableTypeRequest
DrawableTypeRequest(Class<ModelType> modelClass, ModelLoader<ModelType, InputStream> streamModelLoader, ModelLoader<ModelType, ParcelFileDescriptor> fileDescriptorModelLoader, Context context, Glide glide, RequestTracker requestTracker, Lifecycle lifecycle, RequestManager. OptionsApplier OptionsApplier) {/ / 【 3.2 】 buildProvider super (context, modelClass buildProvider (glide, streamModelLoader, fileDescriptorModelLoader, GifBitmapWrapper.class, GlideDrawable.class, null), glide, requestTracker, lifecycle); this.streamModelLoader = streamModelLoader; this.fileDescriptorModelLoader = fileDescriptorModelLoader; this.optionsApplier = optionsApplier; } DrawableRequestBuilder(Context context, Class<ModelType> modelClass, LoadProvider<ModelType, ImageVideoWrapper, GifBitmapWrapper, GlideDrawable> loadProvider, Glide glide, RequestTracker requestTracker, Lifecycle lifecycle) { super(context, modelClass, loadProvider, GlideDrawable.class, glide, requestTracker, lifecycle); // Default to animating. crossFade(); } GenericRequestBuilder(Context context, Class<ModelType> modelClass, LoadProvider<ModelType, DataType, ResourceType, TranscodeType> loadProvider, Class<TranscodeType> transcodeClass, Glide glide, RequestTracker requestTracker, Lifecycle lifecycle) { this.context = context; this.modelClass = modelClass; this.transcodeClass = transcodeClass; this.glide = glide; this.requestTracker = requestTracker; this.lifecycle = lifecycle; this.loadProvider = loadProvider ! = null ? new ChildLoadProvider<ModelType, DataType, ResourceType, TranscodeType>(loadProvider) : null; if (context == null) { throw new NullPointerException("Context can't be null"); } if (modelClass ! = null && loadProvider == null) { throw new NullPointerException("LoadProvider must not be null"); }}Copy the code
  • 3.2
    • buildProvider
private static <A, Z, R> FixedLoadProvider<A, ImageVideoWrapper, Z, R> buildProvider(Glide glide, ModelLoader<A, InputStream> streamModelLoader, ModelLoader<A, ParcelFileDescriptor> fileDescriptorModelLoader, Class<Z> resourceClass, Class<R> transcodedClass, ResourceTranscoder<Z, R> transcoder) { if (streamModelLoader == null && fileDescriptorModelLoader == null) { return null; } the if (transcoder = = null) {/ / get ResourceTranscoder see [3.2.1] -- > GifBitmapWrapperDrawableTranscoder transcoder = glide.buildTranscoder(resourceClass, transcodedClass); } // see [3.2.2] DataLoadProvider<ImageVideoWrapper, Z> dataLoadProvider = glide.buildDataProvider(ImageVideoWrapper.class, resourceClass); ImageVideoModelLoader<A> modelLoader = new ImageVideoModelLoader<A>(streamModelLoader, fileDescriptorModelLoader); return new FixedLoadProvider<A, ImageVideoWrapper, Z, R>(modelLoader, transcoder, dataLoadProvider); }Copy the code

Here resourceClass = GifBitmapWrapper. Class, transcodedClass = GlideDrawable. Class

  • 3.2.1
    • glide.buildTranscoder
 <Z, R> ResourceTranscoder<Z, R> buildTranscoder(Class<Z> decodedClass, Class<R> transcodedClass) {
        return transcoderRegistry.get(decodedClass, transcodedClass);
    }

Copy the code

From “1.1.2”

 transcoderRegistry.register(GifBitmapWrapper.class, GlideDrawable.class,
                new GifBitmapWrapperDrawableTranscoder(
                        new GlideBitmapDrawableTranscoder(context.getResources(), bitmapPool)));
Copy the code

Get transcoder for GifBitmapWrapperDrawableTranscoder

  • 3.2.2
    • glide.buildDataProvider
 <T, Z> DataLoadProvider<T, Z> buildDataProvider(Class<T> dataClass, Class<Z> decodedClass) {
        return dataLoadProviderRegistry.get(dataClass, decodedClass);
    }

Copy the code

DataClass = ImageVideoWrapper here. Class, decodedClass = resourceClass = GifBitmapWrapper. Class from [1.1.2]

 dataLoadProviderRegistry.register(ImageVideoWrapper.class, GifBitmapWrapper.class,
                new ImageVideoGifDrawableLoadProvider(imageVideoDataLoadProvider, gifDrawableLoadProvider, bitmapPool));
Copy the code

Get DataLoadProvider ImageVideoGifDrawableLoadProvider

  1. DrawableTypeRequest.load

 @Override
    public DrawableRequestBuilder<ModelType> load(ModelType model) {
        super.load(model);
        return this;
    }
    

public GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> load(ModelType model) {
        this.model = model;
        isModelSet = true;
        return this;
    }

Copy the code

The final load is to set some ModuleTypes.

Conclusion:

  1. Glide.withAccess to theRequestManagerObject, and then we go throughRequestManager.loadAccording to themodelTypeAccess to theRequestObject.
  2. GlideAccording to themodelTypegenerateRequestThe factory is adopted and initializedModuleLoaderWhen, it contains anotherModuleLoaderQuote, very clever. See [1.2] for details.
  3. amodelType(modelClass)Corresponding to multipleresourceType(resourceClass), aresourceTypeCorresponds to atranscodedType(transcodedClass)
  4. modelTypeCan be understood as the type of request,String Uri FileAnd so on;resourceTypeCan be interpreted as the result of a request, for exampleStream FileAnd so on;transcodedTypeCan be understood as the image conversion typeDrawable BitmapAnd so on.