由于项目的需要,这几天对Glide的执行过程做了简单的了解,希望对想了解Glide基本用法的朋友能有所帮助。
注意
此系列博客基于Glide V3.7.0版本源码
这里假设朋友们能够在Android Studio中正确引入Glide相关的依赖,如果有不懂的朋友,请参考官方文档引入依赖。
为了让朋友们尽快的了解Glide加载图片的流程,我们就从最简单的方式入手。请看如下代码:
ImageView fullscreenView = (ImageView) findViewById(R.id.fullscreen_view);
String imageUrl = "http://image.url.com";
Glide.with(this)
.load(imageUrl)
.into(fullscreenView);
代码清单1-1
使用Glide加载图片就是这么简单!!!
然而,简单的背后往往隐藏了太多的未知数,那么现在我们就来看看这几行简单代码背后究竟隐藏了哪些奇妙的东西。现在就和博主一起开启Glide的学习之旅吧 :)
一、with(this)
在上述代码清单1-1中,我是在FragmentActivity子类中调用了Glide的with
方法,SO这里的this
即是指FragmentActivity
的子类实例。我们点击查看其源码,如下:
public static RequestManager with(FragmentActivity activity) {
RequestManagerRetriever retriever = RequestManagerRetriever.get();
return retriever.get(activity);
}
首先获取一个RequestManagerRetriever
实例,通过该实例得到RequestManager
对象。我们现在进入RequestManagerRetriever#get(FragmentActivity)
方法中来具体看看RequestManager
的获取过程:
public RequestManager get(FragmentActivity activity) {
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
FragmentManager fm = activity.getSupportFragmentManager();
return supportFragmentGet(activity, fm);
}
}
我们只考虑常规情况下使用的场景(不考虑缓存等情况,后文与此相同),由上面的代码,我们很容易定位到supportFragmentGet
方法:
RequestManager supportFragmentGet(Context context, FragmentManager fm) {
SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm);
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
current.setRequestManager(requestManager);
}
return requestManager;
}
由于我们是初次调用Glide加载图片,所以这里会创建一个新的RequestManager
实例,并存入SupportRequestManagerFragment
的current
实例中。传入RequestManager
对象中的Lifecycle
和RequestManagerTreeNode
我们后面再说。这里需要注意的是,在创建RequestManager
对象时,默认创建了一个RequestTracker
对象和OptionsApplier
对象,以及我们的Glide
对象。
我们进入到RequestManager
的构造函数中,定位到glide
实例的获取过程:
RequestManager(Context context, final Lifecycle lifecycle, RequestManagerTreeNode treeNode,
RequestTracker requestTracker, ConnectivityMonitorFactory factory) {
this.context = context.getApplicationContext();
this.lifecycle = lifecycle;
this.treeNode = treeNode;
this.requestTracker = requestTracker;
this.glide = Glide.get(context);
this.optionsApplier = new OptionsApplier();
//省略其它无关代码
...........................
...........................
}
在上述代码中,我们顺藤摸瓜,来到Glide
类的get
方法中:
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;
}
在获取Glide
的实例过程中,我们看到Glide会从AndroidManifest.xml文件中查询我们注册的GlideModule
。同时将GlideBuilder
和Glide
的实例传入我们注册的GlideModule
的对应方法中。由此我们可以了解到,如果想预先控制Glide
的一些行为,可以在我们的GlideModule
的applyOtions
和registerComponents
方法中做控制。
接下来我们继续查看GlideBuilder
的createGlide
方法,直接定位到方法的最后一行:
new Glide(engine, memoryCache, bitmapPool, context, decodeFormat);
好了,重头戏该上演了,我们来看看Glide
类的构造函数:
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);
}
这个方法相对比较长,但是理解起来较为简单。主要就是注册一些DataLoadProvider、ModelLoader的factory以及几个Transcoder。为了更直观的理解和查询,我将它们罗列成下面三张表:(PS:这三张表对于理解Glide的加载流程很重要)
表1-1 ModelType到DataType的映射表
ID | ModelClass | ResourceClass | DataLoaderFactory |
---|---|---|---|
1 | File | ParcelFileDescriptor | FileDescriptorFileLoader.Factory |
2 | File | InputStream | StreamFileLoader.Factory |
3 | int | ParcelFileDescriptor | FileDescriptorResourceLoader.Factory |
4 | int | InputStream | StreamResourceLoader.Factory |
5 | Integer | ParcelFileDescriptor | FileDescriptorResourceLoader.Factory |
6 | Integer | InputStream | StreamResourceLoader.Factory |
7 | String | ParcelFileDescriptor | FileDescriptorStringLoader.Factory |
8 | String | InputStream | StreamStringLoader.Factory |
9 | Uri | ParcelFileDescriptor | FileDescriptorUriLoader.Factory |
10 | Uri | InputStream | StreamUriLoader.Factory |
11 | URL | InputStream | StreamUrlLoader.Factory |
12 | GlideUrl | InputStream | HttpUrlGlideUrlLoader |