安卓开源库学习之Glide的使用及源码阅读
背景
我在安卓开发学习之Picasso源码简析中介绍了图片加载库Picasso的使用,并分析了其源码。做为和Picasso并驾齐驱的开源图片加载库Glide,功能更强大,体积也更大,我觉得也应该看一下
使用步骤
1、添加依赖
compile 'com.github.bumptech.glide:glide:3.7.0'
// Glide依赖
compile 'com.android.support:support-v4:27.1.1'
添加v4的依赖是因为Glide内部利用了Fragment
2、加载图片
Glide加载图片步骤和Picasso是一样的
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mImage = findViewById(R.id.image);
String url = "https://images7.alphacoders.com/789/thumb-1920-789672.jpg";
Glide.with(this).load(url).into(mImage);
}
效果
源码阅读
Glide#with(activity)
方法源码如下
public static RequestManager with(Activity activity) {
RequestManagerRetriever retriever = RequestManagerRetriever.get(); // 获取RequestManagerRetriever的单例
return retriever.get(activity);
}
调用了RequestManagerRetriever的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);
}
}
如果是在后台线程(也就是非主线程)或sdk<11(这个一般是false,sdk11对应Android3.0,很老的版本了),调用了get(context)方法,此方法代码如下
public RequestManager get(Context context) {
if (context == null) { // 传进来的是null,直接抛异常
throw new IllegalArgumentException("You cannot start a load on a null Context");
} else if (Util.isOnMainThread() && !(context instanceof Application)) { // 如果是在主线程上,并且传进来的不是Application对象
if (context instanceof FragmentActivity) { // 如果传进来的是FragmentActivity
return get((FragmentActivity) context);
} else if (context instanceof Activity) { // 如果传进来的是Activity
return get((Activity) context);
} else if (context instanceof ContextWrapper) { // 如果传进来的是Activity的父类ContextWrapper
return get(((ContextWrapper) context).getBaseContext());
}
}
return getApplicationManager(context); // 如果传进来的不是FragmentActivity、Activity、ContextWrapper,就获取ApplicationManager
}
通过看前面的get(activity),发现这里是由非主线程的分支走过来的,并且传进来的是ApplicationContext,这是一个Application对象,所以最后调用的是getApplicationManager(context)方法,代码如下
private RequestManager getApplicationManager(Context context) {
// Either an application context or we're on a background thread.
if (applicationManager == null) {
synchronized (this) {
if (applicationManager == null) {
// Normally pause/resume is taken care of by the fragment we add to the fragment or activity.
// However, in this case since the manager attached to the application will not receive lifecycle
// events, we must force the manager to start resumed using ApplicationLifecycle.
applicationManager = new RequestManager(context.getApplicationContext(),
new ApplicationLifecycle(), new EmptyRequestManagerTreeNode());
}
}
}
return applicationManager;
}
就是返回一个RequestManager单例,构造方法传入的参数分别是应用上下文、应用生命周期、空的请求树,暂时不用管
返回RequestManagerRetriever的get(activity)方法,如果是在主线程,就通过activity的FragmentManager,调用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;
}
调用了getRequestManagerFragment()方法,代码如下
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
RequestManagerFragment getRequestManagerFragment(final android.app.FragmentManager fm) {
RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG); // 第一次使用的话,这里肯定是null
if (current == null) {
current = pendingRequestManagerFragments.get(fm); // pendingRequestManagerFragments是一个哈希映射,但我们第一次进去,肯定也是返回null
if (current == null) {
current = new RequestManagerFragment(); // 构造一个RequestManagerFragment
pendingRequestManagerFragments.put(fm, current); // 存入哈希映射
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss(); // 开始进行fragment转换,添加标签,不进行状态检查
handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
fragment转换完成后,给自己send一个ID_REMOVE_FRAGMENT_MANAGER消息,把刚刚存入的RequestManagerFragment从哈希映射中去掉
@Override
public boolean handleMessage(Message message) {
boolean handled = true;
Object removed = null;
Object key = null;
switch (message.what) {
case ID_REMOVE_FRAGMENT_MANAGER:
android.app.FragmentManager fm = (android.app.FragmentManager) message.obj;
key = fm;
removed = pendingRequestManagerFragments.remove(fm);
break;
...
}
...
return handled;
}
返回getRequestManagerFragment()方法,一切正常的话,就会返回新建的RequestManagerFragment对象到fragmentGet()方法中,而后调用RequestManagerFragment的getRequestManager()方法,获取它的requestManager对象,但是RequestManagerFragment的构造方法里,只会初始化自己的ActivityFragmentLifeCycle,不会实例化requestManager,所以RequestManagerFragment的getRequestManager()方法返回null,然后就是构造一个requestManager对象,set给RequestManagerFragment,最后返回requestManager对象
这样,一路返回,Glide.with(activity)也执行完了,返回的是一个RequestManager,那load()方法执行的就是RequestManager.load()方法
RequestManager#load(string)
代码如下
public DrawableTypeRequest<String> load(String string) {
return (DrawableTypeRequest<String>) fromString().load(string);
}
调用了fromString()方法,代码如下
public DrawableTypeRequest<String> fromString() {
return loadGeneric(String.class); // 似乎用了反射
}
调用了loadGeneric()方法,传入的是class
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.buildStreamModelLoader()方法 public static <T> ModelLoader<T, InputStream> buildStreamModelLoader(Class<T> modelClass, Context context) {
return buildModelLoader(modelClass, InputStream.class, context);
}
进入buildModelLoader方法
public static <T, Y> ModelLoader<T, Y> buildModelLoader(Class<T> modelClass, Class<Y> resourceClass,
Context context) {
if (modelClass == null) {
..
}
return Glide.get(context).getLoaderFactory().buildModelLoader(modelClass, resourceClass);
}
传入的class当然不是空,而后进入Glide.get(context)方法
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单例,debug到此处时,发现之前没有察觉到Glide单例的创建,但这里单例却不是null,原因何在。其实早在我们构造RequestManager的时候,就调用了这个Glide.get()方法,而且,一路跟过来的context参数,也是RequestManager的context对象,同样是在RequestManager的构造方法中传入的,这个构造方法代码如下
public RequestManager(Context context, Lifecycle lifecycle, RequestManagerTreeNode treeNode) { // 这是我们实际调用的
this(context, lifecycle, treeNode, new RequestTracker(), new ConnectivityMonitorFactory());
}
RequestManager(Context context, final Lifecycle lifecycle, RequestManagerTreeNode treeNode,
RequestTracker requestTracker, ConnectivityMonitorFactory factory) {
this.context = context.getApplicationContext(); // 传入的context是Activity,但为了避免内存泄漏,这里赋值的是应用的上下文
this.lifecycle = lifecycle; // RequestManagerFragment里的ActivtiyFragmentLifeCycle对象
this.treeNode = treeNode; // null
this.requestTracker = requestTracker; // new出来的RequestTracker对象
this.glide = Glide.get(context); // 调用Gilde.get()方法获取单例
this.optionsApplier = new OptionsApplier();
ConnectivityMonitor connectivityMonitor = factory.build(context,
new RequestManagerConnectivityListener(requestTracker)); // 构造ConnectivityMonitor
// 给lifeCycle添加监听,监听为RequestManager本身
if (Util.isOnBackgroundThread()) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
lifecycle.addListener(RequestManager.this);
}
});
} else {
lifecycle.addListener(this);
}
lifecycle.addListener(connectivityMonitor); // 给lifeCycle添加监听,监听是ConnectivityMonitor
}
大体看过后,回到Glide.get(context)方法
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(); // 获取当前项目中的所有GlideModule,存在meta-data里,默认没有
GlideBuilder builder = new GlideBuilder(applicationContext); // 构造GlideBuilder,传入全局上下文
for (GlideModule module : modules) { // 这个循环可以忽略
module.applyOptions(applicationContext, builder);
}
glide = builder.createGlide();
for (GlideModule module : modules) { // 这个循环可以忽略
module.registerComponents(applicationContext, glide);
}
}
}
}
return glide;
}
主要是调用了GildeBuilder.createGlide()方法,代码如下
Glide createGlide() {
if (sourceService == null) {
final int cores = Math.max(1, Runtime.getRuntime().availableProcessors());
sourceService = new FifoPriorityThreadPoolExecutor(cores); // 获取服务端或网络数据用的线程池,容量是手机cpu数量,先进先出,并行的
}
if (diskCacheService == null) {
diskCacheService = new FifoPriorityThreadPoolExecutor(1); // 存入缓存用的线程池,容量是1,先进先出,也就是串行的
}
MemorySizeCalculator calculator = new MemorySizeCalculator(context); // 内存大小计算器
if (bitmapPool == null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { // Android3.0以上的bitmapPool遵循LRU(清除最近最久未使用的对象)原则
int size = calculator.getBitmapPoolSize();
bitmapPool = new LruBitmapPool(size);
} else {
bitmapPool = new BitmapPoolAdapter();
}
}
if (memoryCache == null) {
memoryCache = new LruResourceCache(calculator.getMemoryCacheSize()); // 内存缓存也是用的LRU算法
}
if (diskCacheFactory == null) {
diskCacheFactory = new InternalCacheDiskCacheFactory(context); // 存盘缓存
}
if (engine == null) {
engine = new Engine(memoryCache, diskCacheFactory, diskCacheService, sourceService); // 加载器,是加载网络图片或存储空间图片的主力
}
if (decodeFormat == null) {
decodeFormat = DecodeFormat.DEFAULT; // 默认解码器
}
return new Glide(engine, memoryCache, bitmapPool, context, decodeFormat);
}
构造完组件后,就new一个Glide对象返回。
当然,我们从Glide.buildModeLoader()进入的,单例不是null,直接就从Glide.get()里返回了。然后调用glide.getLoaderFactory()方法,获取loaderFactory对象,这个对象是在Glide的构造方法中被初始化的,是一个GenericFactory对象,最后调用genericLoaderFactory的buildModelLoader()方法,传入参数分别是String的class和InputStream.class,方法代码如下
public synchronized <T, Y> ModelLoader<T, Y> buildModelLoader(Class<T> modelClass, Class<Y> resourceClass) {
ModelLoader<T, Y> result = getCachedLoader(modelClass, resourceClass); // 从缓存中读取,第一次进入,返回null
if (result != null) {
// 如果缓存中有我们的ModelLoader,就看情况返回,但第一次加载肯定是没有缓存的
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()方法里,代码如下
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) {
.. // 其他情况
}
return result;
}
从modelClassToResourceFactories这个哈希映射里通过modelClass获取叫做resourceToFactories的哈希映射,这个modelClassToResourceFactories早在Glide的构造方法中就已经添加了内容,相关代码如下
Glide(Engine engine, MemoryCache memoryCache, BitmapPool bitmapPool, Context context, DecodeFormat decodeFormat) {
..
loaderFactory = new GenericLoaderFactory(context);
..
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());
..
}
Glide.register()方法代码如下
public <T, Y> void register(Class<T> modelClass, Class<Y> resourceClass, ModelLoaderFactory<T, Y> factory) {
ModelLoaderFactory<T, Y> removed = loaderFactory.register(modelClass, resourceClass, factory); // 注册,并获取之前注册的ModelLoaderFactory
if (removed != null) {
removed.teardown(); // 销毁之前的ModelLoaderFactory
}
}
我们知道,这里的loaderFactory就是GenericLoaderFactory,它的register()方法代码如下
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); // 先获取以前的modelClass对应的内容,也是一个哈希映射
if (resourceToFactories == null) { // 以前内容是空的话
resourceToFactories = new HashMap<Class/*Y*/, ModelLoaderFactory/*T, Y*/>(); // 构造一个新的hashMap
modelClassToResourceFactories.put(modelClass, resourceToFactories); // 把新的哈希映射做为值,modelClass做为键,存入modelClassToResourceFactories
}
ModelLoaderFactory/*T, Y*/ previous = resourceToFactories.put(resourceClass, factory); // 把参数保存到做为内容的哈希映射中,同时获取老的ModelLoaderFactory
if (previous != null) { // 如果老的ModelLoaderFactory不是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;
}
所以RequestManager.load()里面可以传入的有String、URI、URL、File、Integer、byte数组这些东西,而这些表示图片或图片位置的参数对应的结果也各有各的不同,比如String就对应了InputStream和FileDescriptor两种
返回GenericLoaderFactory.getFactory(),我们根据String.class成功从modelClassToResourceFactories映射中获取了resourceToFactories映射,而且不是null,然后返回这个映射到了GenericLoaderFactory.getFactory()方法中,然后根据resourceClass(也就是InputStream.class)获取对应的ModelLoaderFactory,结果是StreamStringLoader.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); // 此处是StreamStringLoader.Factory对象,ModelLoaderFactory是一个接口,StreamStringLoader.Factory是它的实现类之一
}
if (result == null) {
..
}
return result;
}
而后返回这个StreamStringLoader到GenericLoaderFactory.buildModelLoader()方法中
public synchronized <T, Y> ModelLoader<T, Y> buildModelLoader(Class<T> modelClass, Class<Y> resourceClass) {
ModelLoader<T, Y> result = getCachedLoader(modelClass, resourceClass);
if (result != null) {
// 缓存
if (NULL_MODEL_LOADER.equals(result)) {
return null;
} else {
return result;
}
}
final ModelLoaderFactory<T, Y> factory = getFactory(modelClass, resourceClass); // 已经获取到了StreamStringLoader.Factory
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;
}
而后调用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) {
return new StreamStringLoader(factories.buildModelLoader(Uri.class, InputStream.class)); // 把String.class换成Uri.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);
}
}
执行过程就是把String.class换成Uri.class,再执行一遍GenericLoaderFactory.buildModelLoader()方法,经过GenericLoaderFactory.getFactory()方法,获取到的是StreamUriLoader.Factory,再调用StreamUriLoader.Factory.build()方法,此时把Uri.class换成GlideUrl.class,再执行一遍GenericLoaderFactory.buildModelLoader()方法,经过GenericLoaderFactory.getFactory()方法,获取到的是HttpUrlGlideUrlLoader.Factory,最后调用它的build()方法,获取到一个HttpUrlGlideUrlLoader,这部分的代码如下
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); // 返回的是一个HttpUrlGlideUrlLoader,附带容量是500的缓存
}
@Override
public void teardown() {
// Do nothing.
}
}
...
}
然后一路返回并缓存,GenericLoaderFactory.buildModeLoader()方法也执行完了,再一路返回,回到RequestManager.loadGeneric()方法,这是我们执行完了第一行代码,获得了一个StreamStringLoader对象
private <T> DrawableTypeRequest<T> loadGeneric(Class<T> modelClass) {
ModelLoader<T, InputStream> streamModelLoader = Glide.buildStreamModelLoader(modelClass, context); // 获取到的是一个StringStreamLoader对象
ModelLoader<T, ParcelFileDescriptor> fileDescriptorModelLoader =
Glide.buildFileDescriptorModelLoader(modelClass, context);
if (modelClass != null && streamModelLoader == null && fileDescriptorModelLoader == null) {
// 异常
}
return optionsApplier.apply(
new DrawableTypeRequest<T>(modelClass, streamModelLoader, fileDescriptorModelLoader, context,
glide, requestTracker, lifecycle, optionsApplier));
}
然后调用Glide.buildFileDescriptorModelLoader()方法,这个方法和上面Glide.buildStreamModelLoader()方法流程类似,只是把resourceClass由InputStream.class换成了ParcelFileDescriptor
public static <T> ModelLoader<T, ParcelFileDescriptor> buildFileDescriptorModelLoader(Class<T> modelClass,
Context context) {
return buildModelLoader(modelClass, ParcelFileDescriptor.class, context);
}
所以,简短截说,这里最终返回的是一个FileDescriptorStringLoader对象
返回RequestManager.loadGeneric()方法,最后的apply(),就是把参数里new出来的DrawableTypeRequest对象返回出来,而DrawableTypeRequest对象的构造方法,就是对属性的简单赋值
而后一路返回,返回到RequestManager.load(string)方法
public DrawableTypeRequest<String> load(String string) {
return (DrawableTypeRequest<String>) fromString().load(string);
}
我们刚刚过完的是fromString()方法,获取到了一个DrawableTypeRequest对象,接下来执行的,是它的load(string)方法。但DrawableTypeRequest没有实现load(string)方法,所以执行的是其父类DrawableRequestBuilder的load(string)方法
@Override
public DrawableRequestBuilder<ModelType> load(ModelType model) {
super.load(model);
return this;
}
再往父类里面走,是GenericRequestBuilder.load()方法
public GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> load(ModelType model) {
this.model = model;
isModelSet = true;
return this;
}
原来就是把字符串赋值给了model属性
这样RequestManager.load(string)方法也执行完了,主要是根据String获取了一个StreamStringLoader和FileDescriptorStringLoader,并且把它们俩和String的内容存到一个DrawableTypeRequest对象中,最后把DrawableTypeRequest对象返回。接下来,我们执行最后一步:into(ImageView)
DrawableTypeRequest#into(ImageView)
实际上,DrawableTypeRequest没有实现into()方法,调用的还是父类DrawableRequestBuilder的into()方法
@Override
public Target<GlideDrawable> into(ImageView view) {
return super.into(view);
}
继续向父类追溯,到了GenericRequestBuilder.into(view)方法
public Target<TranscodeType> into(ImageView view) {
Util.assertMainThread();
.. // view的判空
if (!isTransformationSet && view.getScaleType() != null) {
switch (view.getScaleType()) {
case CENTER_CROP:
applyCenterCrop();
break;
case FIT_CENTER:
case FIT_START:
case FIT_END: // 默认是applyFitCenter,把glide里的drawableFitCenter对象赋值给DrawableRequestBuilder对象
applyFitCenter();
break;
//$CASES-OMITTED$
default:
// Do nothing.
}
}
return into(glide.buildImageViewTarget(view, transcodeClass));
}
主要是是执行里面的into(target)方法,不过先执行的是glide.buildImageViewTarget()方法,代码如下
<R> Target<R> buildImageViewTarget(ImageView imageView, Class<R> transcodedClass) {
return imageViewTargetFactory.buildTarget(imageView, transcodedClass);
}
调用了ImageViewTargetFactory.buildTarget()方法,代码如下
public class ImageViewTargetFactory {
@SuppressWarnings("unchecked")
public <Z> Target<Z> buildTarget(ImageView view, Class<Z> clazz) { // 传入的clazz是GlideDrawable
if (GlideDrawable.class.isAssignableFrom(clazz)) {
return (Target<Z>) new GlideDrawableImageViewTarget(view); // 进入这个分支,new一个GlideDrawableImageViewTarget对象
} else if (Bitmap.class.equals(clazz)) {
return (Target<Z>) new BitmapImageViewTarget(view);
} else if (Drawable.class.isAssignableFrom(clazz)) {
return (Target<Z>) new DrawableImageViewTarget(view);
} else {
.. // 异常
}
}
}
获取一个GlideDrawableImageViewTarget对象后,返回到GenericRequestBuilder.into(view)方法中,立马进入GenericRequestBuilder.into(target)方法里
public <Y extends Target<TranscodeType>> Y into(Y target) {
Util.assertMainThread();
.. // 异常检测
Request previous = target.getRequest(); // 第一次是null
if (previous != null) { // 取消之前的request
previous.clear();
requestTracker.removeRequest(previous);
previous.recycle();
}
Request request = buildRequest(target); // 构造一个request(此处是GenericRequest对象),默认直接调用GenericRequestBuilder.obtainRequest()方法,进行一些属性的赋值,最主要的是把glide.engine和model(也就是我们的图片网址)赋值给request中
target.setRequest(request); // 把request做为标签,和GlideDrawableImageViewTarget联系起来
lifecycle.addListener(target); // 并且GlideDrawableImageViewTarget也是一个FragmentActivityLifecycle的监听器
requestTracker.runRequest(request); // 添加到RequestTracker的请求队列中
return target;
}
这样,就已经构造好了请求,并且添加到了请求队列中。
那么这个请求何时发起呢?在最开始Glide.with(activity)方法中,我们曾把一个RequestManagerFragment和我们的activty绑定到了一起,所以在我们的activity生命周期执行到onStart()的时候,RequestManagerFragment也会执行到onStart(),代码如下
@Override
public void onStart() {
super.onStart();
lifecycle.onStart();
}
我们知道lifeCycle是一个ActivityFragmentLifecycle对象,它的onStart()方法的代码如下
void onStart() {
isStarted = true;
for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
lifecycleListener.onStart();
}
}
遍历lifecycle的监听器,经过前面的分析,我们知道监听器有三个:GlideDrawableImageViewTarget、RequestManager和NullConnectivityMonitor
GlideDrawableImageViewTarget的onStart()方法代码如下
@Override
public void onStart() {
if (resource != null) { // resource是null
resource.start();
}
}
由于我们还没发请求,所以resource是null,这个方法就成了摆设
最主要的,就是是RequestManager的onStart()方法,代码如下
@Override
public void onStart() {
// onStart might not be called because this object may be created after the fragment/activity's onStart method.
resumeRequests();
}
调用了resumeRequest()方法,代码如下
public void resumeRequests() {
Util.assertMainThread(); // 确保是主线程
requestTracker.resumeRequests();
}
又调用了requestTracker的resumeRequests()方法,再跟
public void resumeRequests() {
isPaused = false;
for (Request request : Util.getSnapshot(requests)) {
if (!request.isComplete() && !request.isCancelled() && !request.isRunning()) {
request.begin();
}
}
pendingRequests.clear();
}
遍历request队列,依次执行没有完成取消也不在运行着的请求。我们的请求是GenericRequest,它的begin()方法源码如下
@Override
public void begin() {
startTime = LogTime.getLogTime();
.. // model的判空
status = Status.WAITING_FOR_SIZE;
if (Util.isValidDimensions(overrideWidth, overrideHeight)) { // 两个参数默认都是-1,所以判断不成立
onSizeReady(overrideWidth, overrideHeight);
} else {
target.getSize(this); // 进入这个分支,获取GlideDrawableIamgeViewTarget的尺寸,其实就是ImageView的尺寸
}
if (!isComplete() && !isFailed() && canNotifyStatusChanged()) {
target.onLoadStarted(getPlaceholderDrawable()); // 在加载之前,先设置一个占位符,不过默认是null,一片空白
}
.. // 日志
}
可以看到,在三个方法中,主要是调用了target.getSize()方法,代码如下
@Override
public void getSize(SizeReadyCallback cb) {
sizeDeterminer.getSize(cb);
}
调用的是sizeDeterminer.getSize(cb)方法,代码如下 public void getSize(SizeReadyCallback cb) {
int currentWidth = getViewWidthOrParam();
int currentHeight = getViewHeightOrParam();
if (isSizeValid(currentWidth) && isSizeValid(currentHeight)) {
cb.onSizeReady(currentWidth, currentHeight);
} else {
..
}
}
以宽度为例,调用了getViewWidthOrParam()方法,代码如下
private int getViewWidthOrParam() {
final LayoutParams layoutParams = view.getLayoutParams();
if (isSizeValid(view.getWidth())) { // width > 0 或 width == WRAP_CONTENT(-2)才为真
return view.getWidth();
} else if (layoutParams != null) { //所以我这儿走的是第二个分支,返回屏幕的宽度
return getSizeForParam(layoutParams.width, false /*isHeight*/);
} else {
return PENDING_SIZE;
}
}
获取尺寸后,返回sizeDeterminer.getSize(cb)方法,调用cb.onSizeReady()方法,传入尺寸。这里的回调,就是GenericRequest对象,它的onSizeReady()方法代码如下
@Override
public void onSizeReady(int width, int height) {
.. // 日志 + 状态
width = Math.round(sizeMultiplier * width); // sizeMultiplier是图片的缩放倍数,默认是1
height = Math.round(sizeMultiplier * height);
ModelLoader<A, T> modelLoader = loadProvider.getModelLoader(); // 获取的是ImageVideoModelLoader
final DataFetcher<T> dataFetcher = modelLoader.getResourceFetcher(model, width, height); // 获取的是ImageVideoModelLoader.ImageVideoFethcer
if (dataFetcher == null) {
.. // 异常处理
}
ResourceTranscoder<Z, R> transcoder = loadProvider.getTranscoder(); // 转码器,支持gif
.. // 日志
loadedFromMemoryCache = true;
loadStatus = engine.load(signature, width, height, dataFetcher, loadProvider, transformation, transcoder,
priority, isMemoryCacheable, diskCacheStrategy, this);
loadedFromMemoryCache = resource != null;
.. 日志
}
然后主要是调用了engine.load()方法,代码如下
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(); // fetcher的id就是图片的网址
EngineKey key = keyFactory.buildKey(id, signature, width, height, loadProvider.getCacheDecoder(),
loadProvider.getSourceDecoder(), transformation, loadProvider.getEncoder(),
transcoder, loadProvider.getSourceEncoder());
.. // 尝试从缓存中读取图片
.. // 尝试从资源中读取图片
.. // 如果有EngineJob处理这个请求,就返回一个LoadStatus
EngineJob engineJob = engineJobFactory.build(key, isMemoryCacheable); // 处理请求的engineJob
DecodeJob<T, Z, R> decodeJob = new DecodeJob<T, Z, R>(key, width, height, fetcher, loadProvider, transformation,
transcoder, diskCacheProvider, diskCacheStrategy, priority); // 解码job
EngineRunnable runnable = new EngineRunnable(engineJob, decodeJob, priority); // 主要的图片获取和解码工作有EngineRunnable完成
jobs.put(key, engineJob); // 存入engineJob
engineJob.addCallback(cb); // 添加缓存,这里是GenericRequest
engineJob.start(runnable); // 开启线程
.. // 日志
return new LoadStatus(cb, engineJob); // 把回调和engineJob存入LoadStatus的属性里
}
可见,获取图片数据并解码,就在EngineRunnable的run()方法中,代码如下
@Override
public void run() {
if (isCancelled) {
return;
}
Exception exception = null;
Resource<?> resource = null;
try {
resource = decode();
} catch (Exception e) {
.. // 异常
}
if (isCancelled) {
// 回收resource
}
if (resource == null) {
onLoadFailed(exception);
} else {
onLoadComplete(resource);
}
}
调用了decode()方法,代码如下
private Resource<?> decode() throws Exception {
if (isDecodingFromCache()) { // 试着从缓存中读取解码
return decodeFromCache();
} else {
return decodeFromSource();
}
}
我们看decodeFromSource(),因为第一次缓存里不可能有东西
private Resource<?> decodeFromSource() throws Exception {
return decodeJob.decodeFromSource();
}
调用了decodeJob.decodeFromSource()
public Resource<Z> decodeFromSource() throws Exception {
Resource<T> decoded = decodeSource();
return transformEncodeAndTranscode(decoded);
}
进入decodeSource()
private Resource<T> decodeSource() throws Exception {
Resource<T> decoded = null;
try {
long startTime = LogTime.getLogTime();
final A data = fetcher.loadData(priority); // 此处的fetcher是ImageVideoFetcher,优先级是普通
.. // 日志+状态
decoded = decodeFromSourceData(data);
} finally {
fetcher.cleanup();
}
return decoded;
}
进入ImageVideoFetcher.loadData()中
@Override
public ImageVideoWrapper loadData(Priority priority) throws Exception {
InputStream is = null;
if (streamFetcher != null) {
try {
is = streamFetcher.loadData(priority); // 这里的steamFethcer就是HttpUrlFetcher
} catch (Exception e) {
.. //异常
}
}
.. // 试着从fileDescriptor中读取
return new ImageVideoWrapper(is, fileDescriptor);
}
进入HttpUrlFetcher.loadData()方法
@Override
public InputStream loadData(Priority priority) throws Exception {
return loadDataWithRedirects(glideUrl.toURL(), 0 /*redirects*/, null /*lastUrl*/, glideUrl.getHeaders());
}
获取URL和headers后,进入loadDataWithRedirects()方法
private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl, Map<String, String> headers)
throws IOException {
if (redirects >= MAXIMUM_REDIRECTS) { // 重连次数检测
.. // 异常
} else {
.. // url异常检测
}
urlConnection = connectionFactory.build(url); // 构建url链接(其实就是url.openConnection())并设置属性
for (Map.Entry<String, String> headerEntry : headers.entrySet()) {
urlConnection.addRequestProperty(headerEntry.getKey(), headerEntry.getValue());
}
urlConnection.setConnectTimeout(2500);
urlConnection.setReadTimeout(2500);
urlConnection.setUseCaches(false);
urlConnection.setDoInput(true);
// Connect explicitly to avoid errors in decoders if connection fails.
urlConnection.connect(); // url开始连接
if (isCancelled) {
return null;
}
final int statusCode = urlConnection.getResponseCode(); // 状态码
if (statusCode / 100 == 2) {
return getStreamForSuccessfulRequest(urlConnection); // 获取输入流
} else if (statusCode / 100 == 3) {
.. // 重连
return loadDataWithRedirects(redirectUrl, redirects + 1, url, headers);
} else {
.. // 抛出异常
}
}
成功获取url的输入流后,就是ImageVideoBitmapDecoder的解码工作了,这里直接忽略掉。然后获取Resource(这里就是BitmapDrawableResource),回到EngineRunnable.run()方法,一切顺利的话,会走到onLoadCompelete()方法中,传入resource,调用EngineJob.onResourceReady(reource)方法,设置resource,给主线程的handler发送compelete消息
@Override
public void onResourceReady(final Resource<?> resource) {
this.resource = resource;
MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();
}
主线程handler是在回调里处理消息的
private static class MainThreadCallback implements Handler.Callback {
@Override
public boolean handleMessage(Message message) {
if (MSG_COMPLETE == message.what || MSG_EXCEPTION == message.what) {
EngineJob job = (EngineJob) message.obj;
if (MSG_COMPLETE == message.what) {
job.handleResultOnMainThread();
} else {
job.handleExceptionOnMainThread();
}
return true;
}
return false;
}
}
成功的话,调用的是EngineJob.handleResultOnMainThread()方法,在主线程渲染UI,代码如下
private void handleResultOnMainThread() {
..
engineResource = engineResourceFactory.build(resource, isCacheable); // 通过resource获取engineResource,其实就是两个属性的赋值
hasResource = true;
// Hold on to resource for duration of request so we don't recycle it in the middle of notifying if it
// synchronously released by one of the callbacks.
engineResource.acquire(); // 确保是在主线程
listener.onEngineJobComplete(key, engineResource); // listener是Engine,从jobs中移除这个请求
for (ResourceCallback cb : cbs) {
if (!isInIgnoredCallbacks(cb)) {
engineResource.acquire();
cb.onResourceReady(engineResource); // 这里的回调是GenericRequest
}
}
// Our request is complete, so we can release the resource.
engineResource.release();
}
主要是调用了GenericRequest.onResourceReady(resource)方法,代码如下
@Override
public void onResourceReady(Resource<?> resource) {
if (resource == null) {
.. // 异常
}
Object received = resource.get(); // 获取resource中的图片对象,这里是GlideDrawable,继承自BitmapDrawable
if (received == null || !transcodeClass.isAssignableFrom(received.getClass())) {
.. // 异常
}
if (!canSetResource()) {
.. // 不能设置就释放
}
onResourceReady(resource, (R) received);
}
调用了onResourceReady(resource, 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);
}
..
.. // 日志
}
主要是调用了target.onResourceReady()方法,这里的target是GlideDrawableImageViewTarget,不过调用的是其父类ImageViewTarget的这个方法
@Override
public void onResourceReady(Z resource, GlideAnimation<? super Z> glideAnimation) {
if (glideAnimation == null || !glideAnimation.animate(resource, this)) {
setResource(resource);
}
}
不在动画中,就调用setResource()方法,这个方法由子类实现,GlideDrawableImageViewTarget的实现如下
@Override
protected void setResource(GlideDrawable resource) {
view.setImageDrawable(resource);
}
至此,一张图片加载完毕
结语
Glide使用和Picasso差不多,但由于功能上的不一样,源码复杂度也大相径庭。最亮眼的就是Glide把图片的加载同activity的生命周期关联在了一起。