androidAndroid知识Android技术知识

Glide 源码分析之二 load

2017-05-17  本文已影响99人  sunrain_

前言

在上篇中分析完了 with() 方法,Glide 分析之一 with.
本篇中,我们将通过 with() 方法返回的 RequestManager,来分析 load(resourceId) 的执行过程。

load

load() 方法在 RequestManager 中有8种重载,结合本篇的问题,这里只分析 load(resourceId) 方法。

public DrawableTypeRequest<Integer> load(Integer resourceId) {
    return (DrawableTypeRequest<Integer>) fromResource().load(resourceId);(锚点1)
}

load(Integer resourceId) 方法内先调用了 fromResource() 方法:
```java`
public DrawableTypeRequest<Integer> fromResource() {
return (DrawableTypeRequest<Integer>) loadGeneric(Integer.class)(锚点2)
.signature(ApplicationVersionSignature.obtain(context));
}

看 loadGeneric(Integer.class) 方法:
```java
private <T> DrawableTypeRequest<T> loadGeneric(Class<T> modelClass) {
    ModelLoader<T, InputStream> streamModelLoader = Glide.buildStreamModelLoader(modelClass, context);
    ModelLoader<T, ParcelFileDescriptor> fileDescriptorModelLoader = Glide.buildFileDescriptorModelLoader(modelClass, context);
    if (modelClass != null && streamModelLoader == null && fileDescriptorModelLoader == null) {
        throw new IllegalArgumentException("省略");
    }

    return optionsApplier.apply(new DrawableTypeRequest<T>(modelClass, streamModelLoader, fileDescriptorModelLoader, context, 
           glide, requestTracker, lifecycle, optionsApplier));
}

方法内部通过 Glide.buildStreamModelLoader() 和 Glide.buildFileDescriptorModelLoader() 方法创建两个 ModelLoader 对象用于图片加载。
这两个方法会根据传入参数,返回相应的 ModelLoader 实现类。本例中,buildStreamModelLoader() 返回 StreamResourceLoader,buildFileDescriptorModelLoader() 返回 FileDescriptorResourceLoader,这两个方法在最后有详细分析。

loadGeneric() 方法最后创建了 DrawableTypeRequest 对象,并返回。

锚点2处执行完之后继续调用 signature() 方法,标记了一个 Key,然后把 DrawableTypeRequest<Integer> 对象返回出去。

上一层拿到 DrawableTypeRequest<Integer> 对象后调用了它的 load(resourceId) 方法(见:锚点1):

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

这里保存了 ModelType,在本例中就是 Integer.class.
最终 Glide.load() 方法返回 DrawableTypeRequest<Integer> 对象。

至此,load() 方法主线流程就分析完毕了,接下来会继续分析 Glide.buildStreamModelLoader() 方法是如何返回 ModelLoader 的。

Glide.buildStreamModelLoader()

public static <T> ModelLoader<T, InputStream> buildStreamModelLoader(Class<T> modelClass, Context context) {
    return buildModelLoader(modelClass, InputStream.class, context);(锚点3)
}

public static <T, Y> ModelLoader<T, Y> buildModelLoader(Class<T> modelClass, Class<Y> resourceClass, Context context) {
    if (modelClass == null) {
        ···
        return null;
    }
    return Glide.get(context).getLoaderFactory().buildModelLoader(modelClass, resourceClass);(锚点4)
}
public synchronized <T, Y> ModelLoader<T, Y> buildModelLoader(Class<T> modelClass, Class<Y> resourceClass) {
    ···
    final ModelLoaderFactory<T, Y> factory = getFactory(modelClass, resourceClass);
    if (factory != null) {
        result = factory.build(context, this);
        ···
    } else {
        ···
    }
    return result;
}

private <T, Y> ModelLoaderFactory<T, Y> getFactory(Class<T> modelClass, Class<Y> resourceClass) {
    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()) {
            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;
}

可以看到在 getFactory() 方法中根据传入的 modelClass 从 modelClassToResourceFactories 中获取了 value
为 ModelLoaderFactory 的 Map,又根据传入的 resourceClass 从 Map 中取出 ModelLoaderFactory 对象。

那么 modelClassToResourceFactories 的数据是在哪里放入的?
在 buildModelLoader() 方法中调用了 Glide.get() 方法(见:锚点4):

public static Glide get(Context context) {
    if (glide == null) {
        synchronized (Glide.class) {
            if (glide == null) {
               ···
                glide = builder.createGlide();
               ···
            }
        }
    }
    return glide;
}
Glide createGlide() {
    ···
    return new Glide(engine, memoryCache, bitmapPool, context, decodeFormat);
}
Glide(Engine engine, MemoryCache memoryCache, BitmapPool bitmapPool, Context context, DecodeFormat decodeFormat) {
    ···
    register(File.class, ParcelFileDescriptor.class, new FileDescriptorFileLoader.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());
    ···
}

public <T, Y> void register(Class<T> modelClass, Class<Y> resourceClass, ModelLoaderFactory<T, Y> factory) {
    ModelLoaderFactory<T, Y> removed = loaderFactory.register(modelClass, resourceClass, factory);
    ···
}
public synchronized <T, Y> ModelLoaderFactory<T, Y> register(Class<T> modelClass, Class<Y> resourceClass,
                                                             ModelLoaderFactory<T, Y> factory) {
    ···
    Map<Class/*Y*/, ModelLoaderFactory/*T, Y*/> resourceToFactories = modelClassToResourceFactories.get(modelClass);
    if (resourceToFactories == null) {
        resourceToFactories = new HashMap<Class/*Y*/, ModelLoaderFactory/*T, Y*/>();
        modelClassToResourceFactories.put(modelClass, resourceToFactories);
    }
    ···
    return previous;
}

从锚点2、锚点3可以知道 modelClass 为 Integer.class,resourceClass 为 InputStream.class,在 Glide 的构造函数找到对应注册的 ModelLoaderFactory 为 StreamResourceLoader.Factory,所以 buildStreamModelLoader() 方法返回的是 StreamResourceLoader 对象。
同理 buildFileDescriptorModelLoader() 方法返回 FileDescriptorResourceLoader 对象。

至此,根据 ModelType,创建 DrawableRequestBuilder 和其中的 ModelLoader,为下一步加载图片做好准备的流程就分析完毕了。

在下一篇中,我们会继续分析 into() 方法:Glide 源码分析之三 into.

谢谢大家。

参考链接

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

上一篇下一篇

猜你喜欢

热点阅读