这里,我使用的Glide版本是基于3.8.0版本,关于Glide源码分析,先找到程序的入口。这里先从Glide的使用方法找入口。首先,最简单的的使用:Glide.with(context).load([Type pararm]).into(view),使用这种方式就能加载图片显示,我们看下其加载图片的流程是怎样的。

首先Glide调用with()方法传入context,方法内部创建了一个RequestManagerRetrier的单例,RequestManagerRetrier调用get()方法,通过传入的context进行一系列判断,获取对应的RequestManager。接着调用load()方法,在这个方法的内部,先是根据传入参数的类型调用了RequestManager的loadGeneric()生成对应泛型的DrawableTypeRequest对象,根据传入参数类型生成对应的ModuleLoader,并传入泛型DrawableTypeRequest对象中。接着,这个DrawableTypeRequest对象调用继承基类GenericRequestBuilder的load()方法,将参数传入。然后,调用into()方法,返回Target<GlideDrawable>实例,同时调用基类GenericRequestBuilder的into()方法,此时泛型类型为GlideDrawable。在基类GenericRequestBuilder的into()方法内部,target被转化为GlideDrawableImageViewTarget实例,通过调用buildRequest(target),获得一个Request实例.我们看如下代码:
Request request = buildRequest(target);
target.setRequest(request);
lifecycle.addListener(target);
requestTracker.runRequest(request);
构建好一个request后,target被添加监听到 lifecycle中,同时requestTracker开始执行这个request,内部核心其实调用了requst的begin()方法。Request是一个接口,这里begin()方法的实现是GenericRequest类中,buildRequest()方法的内部核心调用了GenericRequest.obtain()方法,返回GenericRequest,obtain()方法携带了相关参数数据。这里的lifecycle和requestTracker来自于上述RequestManager的loadGeneric()生成对应泛型的DrawableTypeRequest对象时,获取的RequestManagerRetrirer实例,核心调用了其getApplicationManager()
方法,方法内部传入了ApplicationLifecycle对象,所以看来, lifecycle.addListener(target);这行代码内部已经调用了ApplicationLifecycle的LifecycleListener的onStart()方法,而回调调用了上述的GlideDrawableImageViewTarget的onStart()方法,该方法其实开始执行启动加载动画。requestTracker.runRequest(request)方法开始执行请求数据,此时回调GenericRequest的的begin()。GenericRequest的begin()内部核心调用了onSizeReady()。
@Override
public void begin() {
startTime = LogTime.getLogTime();
if (model == null) {
onException(null);
return;
}
status = Status.WAITING_FOR_SIZE;
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
onSizeReady(overrideWidth, overrideHeight);
} else {
target.getSize(this);
}
if (!isComplete() && !isFailed() && canNotifyStatusChanged()) {
target.onLoadStarted(getPlaceholderDrawable());
}
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("finished run method in " + LogTime.getElapsedMillis(startTime));
}
}
/**
* A callback method that should never be invoked directly.
*/
@Override
public void onSizeReady(int width, int height) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("Got onSizeReady in " + LogTime.getElapsedMillis(startTime));
}
if (status != Status.WAITING_FOR_SIZE) {
return;
}
status = Status.RUNNING;
width = Math.round(sizeMultiplier * width);
height = Math.round(sizeMultiplier * height);
ModelLoader<A, T> modelLoader = loadProvider.getModelLoader();
final DataFetcher<T> dataFetcher = modelLoader.getResourceFetcher(model, width, height);
if (dataFetcher == null) {
onException(new Exception("Failed to load model: \'" + model + "\'"));
return;
}
ResourceTranscoder<Z, R> transcoder = loadProvider.getTranscoder();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime));
}
loadedFromMemoryCache = true;
loadStatus = engine.load(signature, width, height, dataFetcher, loadProvider, transformation, transcoder,
priority, isMemoryCacheable, diskCacheStrategy, this);
loadedFromMemoryCache = resource != null;
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("finished onSizeReady in " + LogTime.getElapsedMillis(startTime));
}
}
onSizeReady()回调中,通过传递的loadProvider获取了dataFetcher 及transcoder,这里的核心是调用了Engine的load()方法。我们调到这个Engine类的方法中看一下,
public <T, Z, R> LoadStatus load(Key signature, int width, int height, DataFetcher<T> fetcher,
DataLoadProvider<T, Z> loadProvider, Transformation<Z> transformation, ResourceTranscoder<Z, R> transcoder,
Priority priority, boolean isMemoryCacheable, DiskCacheStrategy diskCacheStrategy, ResourceCallback cb) {
Util.assertMainThread();
long startTime = LogTime.getLogTime();
final String id = fetcher.getId();
EngineKey key = keyFactory.buildKey(id, signature, width, height, loadProvider.getCacheDecoder(),
loadProvider.getSourceDecoder(), transformation, loadProvider.getEncoder(),
transcoder, loadProvider.getSourceEncoder());
EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
if (cached != null) {
cb.onResourceReady(cached);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Loaded resource from cache", startTime, key);
}
return null;
}
EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
if (active != null) {
cb.onResourceReady(active);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Loaded resource from active resources", startTime, key);
}
return null;
}
EngineJob current = jobs.get(key);
if (current != null) {
current.addCallback(cb);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Added to existing load", startTime, key);
}
return new LoadStatus(cb, current);
}
EngineJob engineJob = engineJobFactory.build(key, isMemoryCacheable);
DecodeJob<T, Z, R> decodeJob = new DecodeJob<T, Z, R>(key, width, height, fetcher, loadProvider, transformation,
transcoder, diskCacheProvider, diskCacheStrategy, priority);
EngineRunnable runnable = new EngineRunnable(engineJob, decodeJob, priority);
jobs.put(key, engineJob);
engineJob.addCallback(cb);
engineJob.start(runnable);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Started new load", startTime, key);
}
return new LoadStatus(cb, engineJob);
}
从代码中看,先是通过传递的dataFetcher 获取对应的id,根据id生成缓存key。这里就进入核心了,和其他加载框架一样,先是根据这个key加载缓存,获取缓存数据,有缓存就取缓存对象。缓存接口MemoryCache管理内存。如果没有缓存,接着就会从当前本地内存中取,这个Resource保存在一个软引用的Map中,通过键key来获取数据。这个map存储的是缓存中的数据。如果当前本地内存也没有,就从保存的EngineJob中获取,这个EngineJob也用一个Map保存。这个EngineJob又是什么数据呢?从EngineJob engineJob = engineJobFactory.build(key, isMemoryCacheable)这行代码进入,我们明白了这里是根据磁盘缓存策略存储的磁盘缓存缓存数据。由此看来,检查完磁盘缓存后,若没有磁盘缓存,接下来就是请求网络。我们看engineJob.start(runnable);这个runnable的run方法被执行,调用decode()方法,接下来就是对缓存数据的解析同时根据缓存策略决定是否去存储数据,这里就不再赘述了。
那么,Glide是怎样请求数据并显示图片在控件上呢?通过对decode()方法的追踪,可以看到最终调用了上述的dataFetcher的loadData()方法,这个loadData()核心逻辑是什么。首先,我们要清楚当前的这个dataFetcher是什么。从上述看,我们必须先弄清楚modelLoader到底是哪一个。跟踪源码,我们发现它 的来源是RequestManager的loadGeneric()中,
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("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");
}
return optionsApplier.apply(
new DrawableTypeRequest<T>(modelClass, streamModelLoader, fileDescriptorModelLoader, context,
glide, requestTracker, lifecycle, optionsApplier));
}
这里,通过深入追踪,与下面Glide类中的这部分代码相关,
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;
}
return
Glide.get(context).getLoaderFactory().buildModelLoader(modelClass, resourceClass);
}
敲黑板,注意这句代码,
Glide.get(context).getLoaderFactory().buildModelLoader(modelClass, resourceClass)。这里实际上先进行了Glide的初始化,在初始化过程中,预先注册了相关的moduleLoader,
Glide(Engine engine, MemoryCache memoryCache, BitmapPool bitmapPool, Context context, DecodeFormat decodeFormat) {
this.engine = engine;
this.bitmapPool = bitmapPool;
this.memoryCache = memoryCache;
this.decodeFormat = decodeFormat;
loaderFactory = new GenericLoaderFactory(context);
mainHandler = new Handler(Looper.getMainLooper());
bitmapPreFiller = new BitmapPreFiller(memoryCache, bitmapPool, decodeFormat);
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());
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());
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);
}
针对当前的流程和参数类型,注意上述红字部分,这里又调用了GenericLoaderFactofy的register()方法,在这个方法中,用一个map集合存储了上述注册的factory对象,
public synchronized <T, Y> ModelLoaderFactory<T, Y> register(Class<T> modelClass, Class<Y> resourceClass,
ModelLoaderFactory<T, Y> factory) {
cachedModelLoaders.clear();
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);
}
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;
}
接着再看Glide.get(context).getLoaderFactory().buildModelLoader(modelClass, resourceClass),
在调用buildModelLoader(),进入到GenericLoaderFactory的buildModuleLoader(),
public synchronized <T, Y> ModelLoader<T, Y> buildModelLoader(Class<T> modelClass, Class<Y> resourceClass) {
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;
}
}
final ModelLoaderFactory<T, Y> factory = getFactory(modelClass, resourceClass);
if (factory != null) {
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;
}
这里,我们看下getFactory(),其实际对上述存储factory集合进行了遍历,并根据参数类型及当前参数类型而构建的resourceClass作为条件,获取当前的对应的factory,
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()) {
// 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;
}
从上述知道,我们当前的第一个factory为StreamStringLoader.Factory,第二个factory为FileDescriptorStringLoader.Factory。所以,我们就明白了,loadGeneric()中的streamModelLoader为StreamStringLoader,fileDescriptorModelLoader为FileDescriptorStringLoader。这里也很符合其命名。
由此,同理跟踪,当前的dataFetcher转化为探索StreamUriLoader.getResourceFetcher()的返回,这里针对以下三种情况的返回,不做一一分析,只选取网络请求的情况.最后追踪到HttpUrlGlideUrlLoader中,最终dataFetcher为HttpUrlFetcher。通过查看HttpUrlFetcher的loadData(),内部采用的是HttpUrlConnection进行的网络请求,线程调度采用的是handler。
public abstract class UriLoader<T> implements ModelLoader<Uri, T> {
private final Context context;
private final ModelLoader<GlideUrl, T> urlLoader;
public UriLoader(Context context, ModelLoader<GlideUrl, T> urlLoader) {
this.context = context;
this.urlLoader = urlLoader;
}
@Override
public final DataFetcher<T> getResourceFetcher(Uri model, int width, int height) {
final String scheme = model.getScheme();
DataFetcher<T> result = null;
if (isLocalUri(scheme)) {
if (AssetUriParser.isAssetUri(model)) {
String path = AssetUriParser.toAssetPath(model);
result = getAssetPathFetcher(context, path);
} else {
result = getLocalUriFetcher(context, model);
}
} else if (urlLoader != null && ("http".equals(scheme) || "https".equals(scheme))) {
result = urlLoader.getResourceFetcher(new GlideUrl(model.toString()), width, height);
}
return result;
}
protected abstract DataFetcher<T> getLocalUriFetcher(Context context, Uri uri);
protected abstract DataFetcher<T> getAssetPathFetcher(Context context, String path);
private static boolean isLocalUri(String scheme) {
return ContentResolver.SCHEME_FILE.equals(scheme)
|| ContentResolver.SCHEME_CONTENT.equals(scheme)
|| ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme);
}
}
而请求成功的数据后,进行了数据保存,先是保存在本地内存中,即上述的map对象activityResource,然后同过调用回调方法release(),根据是否缓存进一步将数据保存在缓存中。
@Override
public void onEngineJobComplete(Key key, EngineResource<?> resource) {
Util.assertMainThread();
// A null resource indicates that the load failed, usually due to an exception.
if (resource != null) {
resource.setResourceListener(key, this);
if (resource.isCacheable()) {
activeResources.put(key, new ResourceWeakReference(key, resource, getReferenceQueue()));
}
}
// TODO: should this check that the engine job is still current?
jobs.remove(key);
}
@Override
public void onResourceReleased(Key cacheKey, EngineResource resource) {
Util.assertMainThread();
activeResources.remove(cacheKey);
if (resource.isCacheable()) {
cache.put(cacheKey, resource);
} else {
resourceRecycler.recycle(resource);
}
}
最后,数据获取后是怎样显示在控件上的呢?我们记得之前engine的load()进行了数据的获取,
EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
if (active != null) {
cb.onResourceReady(active);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Loaded resource from active resources", startTime, key);
}
return null;
}
而这里回调到了GenericRequest的onResourceReady()回调方法,关注核心方法onResourceReady(),因为这里的target是GlideDrawableImageviewTarget,跟踪其onResourceReady()方法,其最终调用了其setResource(),其实现正是view.setImageBitmap(resource),这样图片就显示出来了。
@SuppressWarnings("unchecked")
@Override
public void onResourceReady(Resource<?> resource) {
if (resource == null) {
onException(new Exception("Expected to receive a Resource<R> with an object of " + transcodeClass
+ " inside, but instead got null."));
return;
}
Object received = resource.get();
if (received == null || !transcodeClass.isAssignableFrom(received.getClass())) {
releaseResource(resource);
onException(new Exception("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.")
));
return;
}
if (!canSetResource()) {
releaseResource(resource);
// We can't set the status to complete before asking canSetResource().
status = Status.COMPLETE;
return;
}
onResourceReady(resource, (R) received);
}
*/
private void onResourceReady(Resource<?> resource, R result) {
// We must call isFirstReadyResource before setting status.
boolean isFirstResource = isFirstReadyResource();
status = Status.COMPLETE;
this.resource = resource;
if (requestListener == null || !requestListener.onResourceReady(result, model, target, loadedFromMemoryCache,
isFirstResource)) {
GlideAnimation<R> animation = animationFactory.build(loadedFromMemoryCache, isFirstResource);
target.onResourceReady(result, animation);
}
notifyLoadSuccess();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logV("Resource ready in " + LogTime.getElapsedMillis(startTime) + " size: "
+ (resource.getSize() * TO_MEGABYTE) + " fromCache: " + loadedFromMemoryCache);
}
}
本人阅读源码不多,此篇为首篇源码分析,旨在锻炼和作为学习笔记,可能分析有错误的地方,欢迎指正。