我尽量做到不打错别字,用词准确,不造成阅读障碍。
本文基于Glide3.7.0源码,并不是4.0系列。本系列分为三部分:with()、load()、into();本篇文章只介绍Iwith()和load()两个步骤,因为这两个步骤相对而言比较简单,特别是with(),而into()内容非常复杂,必须单独开一篇,要不然太长了。本文的主要目的在于学习总结,并给需要的人一点帮助,并不奢望多么完美,如有错误,欢迎指出。
一.准备
我们使用最简单的例子:
Glide.with(this).load("字符串地址").into(imageView); //this为MainActivity
所以我们分析的路径也是最简单的情况,不会过细分析,因为太细的分析我就不敢保证正确了,哭~~~
注意: 我个人把Glide的源码解读分为3+3+3 ,第一个"3"指的是with()、load()、into()这三大步。第二个"3"指的是into()中的的三大步:清除旧的request---->构建新的request---->运行新的request。最后一个"3"指的是获取数据的三步:从内存缓存中拿数据—>从磁盘缓存中拿数据—>从网络拿数据并处理,其中"从网络拿数据并处理"比较麻烦,包含拿数据、解码、转换、存入缓存、回调等步骤。可以看出主要步骤都在into()方法里面,所以into()篇幅最长。本文只是三大步中的前两步:with()和load();
二.with()
主要作用:确定生命周期
with()有很多重载的方法:
public static RequestManager with(Context context){...}
public static RequestManager with(Activity activity){...}
public static RequestManager with(FragmentActivity activity){...}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static RequestManager with(android.app.Fragment fragment){...}
public static RequestManager with(Fragemnt fragment){...}
分为两种:Application的context和非Application的context,前者就不说了,生命周期为整个应用程序的生命周期,后者的生命周期就需要处理了,开头的例子中是Activity的那个,代码如下:
public static RequestManager with(Activity activity) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(activity);
}
然后看一下retriever.get(activity)中的方法:
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public RequestManager get(Activity activity) {
if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
android.app.FragmentManager fm = activity.getFragmentManager();
return fragmentGet(activity, fm);
}
}
首先如果是非UI线程或者SDK在3.0以下,就调用get(),传入Application的context;如果都不是,就像例子中一样,则调用fragmentGet(…):
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
RequestManager fragmentGet(Context context, android.app.FragmentManager fm) {
RequestManagerFragment current = getRequestManagerFragment(fm);
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
current.setRequestManager(requestManager);
}
return requestManager;
}
说白了就是创建一个新的fragment,因为Fragment和Activity的生命周期是同步的,通过Fragment来监听Activity的生命周期,这是一个小技巧,最后返回一个RequestManager,生命周期是一个监听函数,作为RequestManager的lifecycle属性传入,后面会用到。所以说with()主要作用就是跟踪Activity的生命周期。
三.load()
主要作用:初始化配置或者说是属性配置||准备工作
这个主要作用可能描述的不好,我略读代码后的感受就是做了很多配置,为后面into()方法先配置属性及资源,像是做铺垫。
之前with()返回了一个RequestManager,其中有context、lifecycle等属性,现在执行RequestManager的load()方法了:
//RequestManager.java
public DrawableTypeRequest<String> load(String string) {
return (DrawableTypeRequest<String>) fromString().load(string);
}
public DrawableTypeRequest<String> fromString() {
return loadGeneric(String.class);
}
其中load()方法比较简单,就是将string参数作为model传入GenericRequestBuilder的Model属性上,后面会用到。所以主要在loadGeneric(String.class):
//RequestManager.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("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));
}
首先是创建了两个ModelLoader:streamModelLoader、fileDescriptorModelLoader,这两个ModelLoader很重要,缓存机制就有这两位的参与。两个Glide.build…(…)方法最后都调用了buildModelLoader(…);方法,前者参数为InputStream.class,后者参数为ParcelFileDescriptor.class,最后都走到了这里:
//Glide.java
return Glide.get(context).getLoaderFactory().buildModelLoader(modelClass, resourceClass);
public static Glide get(Context context) {
if (glide == null) {
synchronized (Glide.class) {
if (glide == null) {
Context applicationContext = context.getApplicationContext();
List<GlideModule> modules = new ManifestParser(applicationContext).parse();
GlideBuilder builder = new GlideBuilder(applicationContext);
for (GlideModule module : modules) {
module.applyOptions(applicationContext, builder);
}
glide = builder.createGlide();
for (GlideModule module : modules) {
module.registerComponents(applicationContext, glide);
}
}
}
}
return glide;
}
其中在get(context)中有一句"builder.createGlide()",这里面有new缓存对象:
//Glide.java
Glide createGlide() {
if (sourceService == null) {
final int cores = Math.max(1, Runtime.getRuntime().availableProcessors());
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();
}
}
if (memoryCache == null) {
//缓存对象
memoryCache = new LruResourceCache(calculator.getMemoryCacheSize());
}
if (diskCacheFactory == null) {
//磁盘缓存工厂
diskCacheFactory = new InternalCacheDiskCacheFactory(context);
}
if (engine == null) {
//new一个Engin对象,这个对象在into()中会用到
engine = new Engine(memoryCache, diskCacheFactory, diskCacheService, sourceService);
}
if (decodeFormat == null) {
decodeFormat = DecodeFormat.DEFAULT;
}
return new Glide(engine, memoryCache, bitmapPool, context, decodeFormat);
}
其中new了一个LruResourceCache(…)的缓存,获得了一个diskCacheFactory,还new了一个engine对象并将获得的cache、factory等等传入进去了,这个Engin在后期into(…)会用到;最后返回一个glide对象,然后用这个对象去创建modelLoader;这个new Glide(…);里面做了非常多的操作,其中注册了许多的工厂。
//Glide.java
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));
//Gif相关
//......
}
其中最重要的是注册了许多的工厂,具体是什么工厂,你看名字也猜出个大概,这也是Java命名规则的好处之一,
所有工厂中最重要的目前是HttpUrlGlideUrlLoader.Factory(),这是真正网络访问获取图片时需要用到的。register(…)方法如下:
//GenericLoaderFactory.java
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);
//...
return previous;
}
可以看到创建了一个resourceFactories的map,然后把factory参数put进去。
到这里为止,创建了两个modelLoader,这里面把缓存配置好了,网络访问的工厂准备好了,还有很多配置,接下来往下走:
//RequestManager.java
return optionsApplier.apply(
new DrawableTypeRequest<T>(modelClass, streamModelLoader, fileDescriptorModelLoader, context,
glide, requestTracker, lifecycle, optionsApplier));
optionsApplier.apply(…)这个方法我不是很理解,主要是配置options这个属性的,注释说是配置一些默认选项,但我没找到设置的地方,哭~,所以在我看来基本结果就是"给啥返啥",给了DrawableTypeRequest就返给你DrawableTypeRequest,那重点就是这个返回的对象做了什么初始化操作?
//DrawableTypeRequest.java
DrawableTypeRequest(Class<ModelType> modelClass, ModelLoader<ModelType, InputStream> streamModelLoader,
ModelLoader<ModelType, ParcelFileDescriptor> fileDescriptorModelLoader, Context context, Glide glide,
RequestTracker requestTracker, Lifecycle lifecycle, RequestManager.OptionsApplier optionsApplier) {
super(context, modelClass,
buildProvider(glide, streamModelLoader, fileDescriptorModelLoader, GifBitmapWrapper.class,
GlideDrawable.class, null),
glide, requestTracker, lifecycle);
this.streamModelLoader = streamModelLoader;
this.fileDescriptorModelLoader = fileDescriptorModelLoader;
this.optionsApplier = optionsApplier;
}
其他的都简单,最重要的就是builderProvider(…),相信你也看出来了,这个方法传入了2个modelLoader、lifecycle、glide等重要参数,返回一个FixedLoadProvider对象,我觉得这里先不要管这个provider具体是干嘛的,要不然容易绕死,只记住返回了一个provider,先进入super(…)方法,:
//DrawabloeRequestBuilder.java
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();
}
现在进入了DrawableRequestBuilder.java中,又是super(…)方法:
//GenericRequestBuilder.java
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");
}
}
这里进入到了GenericRequestBuilder.java 中,这个类很重要,我们三大步中的最后一步——into(…)就是从这里开始的,也就是"3+3+3"中第二个"3"的所在地。可以看到这里传入了非常多的参数作为属性,之前准备的provider、glide、lifecycle、context等等都到了这里,并没有什么复杂的操作,感觉就是为之后的into(…)做准备。
接下来回头看buildProvider(…)方法:
//DrawableTypeRequest.java
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;
}
if (transcoder == null) {
transcoder = glide.buildTranscoder(resourceClass, transcodedClass);
}
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);
}
注意第二个判null,因为我们传进来的就是null,所以这里会进入判断内部去创建一个转换器,用于获取数据以后使用,然后创建了一个dataLoadProvider和modelLoader,前者保存有网络获取的数据流InputStream之类的,在ImageVideoWrapper.class里,后者是into(…)步骤中里真正调用工厂去网络访问的对象,最后这些都会被放入FixedLoadProvider()中。给我的感觉就是准备好了获取数据的对象、准备好了承接inputStream的类、准备好了对数据结果进行转换的类,最后汇集一下,等使用的时候在调用。
整个load(…)步骤大概就这些,其中我认为最重要的就是两个modelLoader:streamModelLoader、fileDescriptorModelLoader,这两个对象对下连接缓存,对上连接数据流,还和网络访问和数据转换在一起搞基,感觉挺厉害,希望重点研究。
设置
使用时经常指定"asBitmap()、asGif()",这两个方法会导致生成不同的"request",后期处理生成不同的对象。
还有"placeholder(…)、error(…)"等,这些方法都是在DrawableRequestBuilder.java中,因为load(…)方法只返回DrawableTypeRequest,而它继承了DrawableRequestBuilder.java,而后者又继承GenericRequestBuilder.java 这个特别重要的类,一个super(…)把所有的东西都扔给你,into(…)步骤时就可以使用了。
关于into(…)的文章在这里:小菜读Glide3.0源码----into()
感谢: