背景
我在安卓开发学习之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的生命周期关联在了一起。