Glide源码分析
Glide 基本使用方式
-
Glide .with(this) .load("https://img1.baidu.com/it/u=4030671121,170372214&fm=26&fmt=auto&gp=0.jpg") .into(binding.ivTest)
-
这就是最简单的使用方法了
- 调用with ,load ,into 方法完成一个图片加载的过程
- 下面我们分析下这三个方法分别做了什么
基本方法分析
- 根据上面说的我们首先来分析with 方法 看其内部做了什么
with(Context)
-
可以看到with方法内部传递了一个context
-
/** * 如果使用任意context(ApplicationContext),请求将只对应于应用程序级别,跟随应用的生命周 * 期,而不会基于Activity或者Fragment的生命周期启动或停止事件。所以我们在应用的时候应该按级别划分,是Activity就用对应activiyt的with 是Fragment 就用对应Fragment的with,从而使图片加载对应活动界面的生命周期 * @see #with(android.app.Activity) * @see #with(android.app.Fragment) * @see #with(android.support.v4.app.Fragment) * @see #with(android.support.v4.app.FragmentActivity) * * @param 任意context * @return 顶级的 RequestManager,可以用来启动加载。 */ public static RequestManager with(Context context) { RequestManagerRetriever retriever = RequestManagerRetriever.get(); return retriever.get(context); } /** * @param 使用的activity * @return 给定的ctivity的RequestManager,可以用来启动加载。 */ public static RequestManager with(Activity activity) { RequestManagerRetriever retriever = RequestManagerRetriever.get(); return retriever.get(activity); } /** * @param 使用的FragmentActivity * @return 给定的FragmentActivity的RequestManager,可以用来启动加载。 */ public static RequestManager with(FragmentActivity activity) { RequestManagerRetriever retriever = RequestManagerRetriever.get(); return retriever.get(activity); } /** * @param 要使用的Fragment * @return 给定fragment的RequestManager,可以用来启动加载。 */ @TargetApi(Build.VERSION_CODES.HONEYCOMB) public static RequestManager with(android.app.Fragment fragment) { RequestManagerRetriever retriever = RequestManagerRetriever.get(); return retriever.get(fragment); } /** * @param 要使用的Fragment * @return 给定fragment的RequestManager,可以用来启动加载。 */ public static RequestManager with(Fragment fragment) { RequestManagerRetriever retriever = RequestManagerRetriever.get(); return retriever.get(fragment); }
-
根据上面的@see我们也可以看出 with方法有多个重载,但是毫无例外,所有的重载返回的都是一个RequestManager的对象
- 那么RequestManager 是干什么的?
- 用于管理和启动Glide请求的类。可以连接Activity和Fragment的生命周期事件,来智能地停止、启动和重新启动请求。
- 这里就有一个有意思的事情了 关联Activity和Fragment 的生面周期来只能的管理请求,那这是怎么实现的,我们带着这个疑问继续往下走
- 用于管理和启动Glide请求的类。可以连接Activity和Fragment的生命周期事件,来智能地停止、启动和重新启动请求。
- 那么RequestManager 是干什么的?
-
如何获取的RequestManager
-
-
- 首先通过RequestManagerRetriever.get();获取RequestManagerRetriever
-
-
再通过retriever.get 获取RequestManager
-
RequestManagerRetriever是什么?做什么用的 ?
- 是一个静态方法集合
- 用于创建RequestManager,或者从现有的Activity和Fragment中获取RequestManager
-
retriever.get
-
public RequestManager get(Context context) {} public RequestManager get(FragmentActivity activity) { } public RequestManager get(Fragment fragment) {} @TargetApi(Build.VERSION_CODES.HONEYCOMB) public RequestManager get(Activity activity) { //判断是否后台线程 或者 是否sdk版本小于11(Android 3.0)是则调用get if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { return get(activity.getApplicationContext()); } else { assertNotDestroyed(activity); // 获取传递进来的Context对应的Fragmentmanager android.app.FragmentManager fm = activity.getFragmentManager(); //调用FragmentGet方法参数为传递进来的context 和 获取的Fragmentmanager return fragmentGet(activity, fm); } }
-
可以看到 其内部分了两种方式来获取requestManager
- 1 get 方法
- 2 通过 fragmentGet(activity, fm)
-
1 通过 get 方法
-
public RequestManager get(Context context) { if (context == null) { throw new IllegalArgumentException("You cannot start a load on a null Context"); } else if (Util.isOnMainThread() && !(context instanceof Application)) { if (context instanceof FragmentActivity) { return get((FragmentActivity) context); } else if (context instanceof Activity) { return get((Activity) context); } else if (context instanceof ContextWrapper) { return get(((ContextWrapper) context).getBaseContext()); } } return getApplicationManager(context); }
-
可以看到其内部做了判断
-
判断是否为空 为空抛出异常
-
判断是否满足是主线程且不是Application类型 满足则 根据类型调用对应的Activity或者Framgnt 的get方法,最终还是执行到下面的 fragmentGet方法里
-
如果上述条件都不满足 则调用getApplicationManager(context); 获取applicaiton对应的RequestManager
-
private RequestManager getApplicationManager(Context context) { if (applicationManager == null) { synchronized (this) { if (applicationManager == null) { //通常,暂停/恢复是由我们添加到Activity,Fragemnt的片段来处理的。然而,在这种情况下,由于附加到应用程序的管理器将不会接收生命周期事件,我们必须强制管理器使用Application的的生命周期来处理Glide的请求。 applicationManager = new RequestManager(context.getApplicationContext(), new ApplicationLifecycle(), new EmptyRequestManagerTreeNode()); } } } return applicationManager; }
-
当是applicationContext的时候由于没有对应的activity,Fragment来监听生命周期 需强制使用Applcation的生命周期来处理Glide的请求
-
-
注意
-
如果with内参数不是Activity 或者fragment或者FragmentActivity,那将不会创建Fragment进行生命周期绑定,而是直接绑定Application的生命周期,这种方式存在弊端就是是能监听Application的生命周期,不能监听宿主界面的生命周期也就不能在这里根据生命周期的变化而加载暂停图片加载了
-
-
-
-
2 通过fragmentGet(activity, fm)方法
我们来观察这个方法-
RequestManager fragmentGet(Context context, android.app.FragmentManager fm) { //1 获取一个RequestManagerFragment RequestManagerFragment current = getRequestManagerFragment(fm); //2 获取RequestManager RequestManager requestManager = current.getRequestManager(); //3 RequestManager若为空 if (requestManager == null) { // 4 创建RequestManager requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode()); //设置RequestManager 一个Fragment对应一个requestmanager current.setRequestManager(requestManager); } return requestManager; }
-
在方法内获取了一个
RequestManagerFragment
并根据创建的RequestManagerFragment
获取requestmanager
下面我们来分析这两个对象的获取过程-
RequestManagerFragment
通过 getRequestManagerFragment(fm)-
RequestManagerFragment getRequestManagerFragment(final android.app.FragmentManager fm) { RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG); if (current == null) { //从待处理的请求管理器集合中获取fragment current = pendingRequestManagerFragments.get(fm); if (current == null) { // 获取不到就创建新的添加到 待处理集合中 current = new RequestManagerFragment(); pendingRequestManagerFragments.put(fm, current); // 将创建的无界面Fragemnt 添加到传递进来的Activity或者Fragment上并绑定,因为这后面才能完成生命周期监听 fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss(); handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget(); } } return current; }
-
上面看到一个pendingRequestManagerFragments
-
这是一个以Fragmentmanager 为key,RequestManagerFragment为value的map集合,一个Fragmentmanager 对应 一个RequestManagerFragment
-
这也是为了避免重复创建RequestManagerFragment
-
看下RequestManagerFragment 代码
public class RequestManagerFragment extends Fragment { private final ActivityFragmentLifecycle lifecycle; // 构建过程中初始化了一个ActivityFragmentLifecycle用于调用生命周期方法 public RequestManagerFragment() { this(new ActivityFragmentLifecycle()); } RequestManagerFragment(ActivityFragmentLifecycle lifecycle) { this.lifecycle = lifecycle; } ActivityFragmentLifecycle getLifecycle() { return lifecycle; } // 在生命周期方法中 调用lifecycle对应方法将事件传递 @Override public void onStart() { super.onStart(); lifecycle.onStart(); } @Override public void onStop() { super.onStop(); lifecycle.onStop(); } @Override public void onDestroy() { super.onDestroy(); lifecycle.onDestroy(); } }
- 观察上面代码在RequestManagerFragment初始化时创建了一个ActivityFragmentLifecycle并在Fragment 对应生命周期中调用ActivityFragmentLifecycle的对应事件所以该类就是用来管理其生命周期回调的也是实现生命周期监听最重要的类
- 在这里我们不分析 具体实现生命周期的原理监听的请参看生命周期监听
-
-
-
RequestManager 通过new RequestManager()
-
public class RequestManager implements LifecycleListener { 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) { //初始化Glide this.glide = Glide.get(context); // 添加生命周期监听事件 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); } // 重写生命周期监听方法 来监听 @Override public void onStart() { resumeRequests(); } @Override public void onStop() { pauseRequests(); } @Override public void onDestroy() { requestTracker.clearRequests(); }
-
在初始化RequestManager的时候 初始化了glide ,同时完成了生命周期方法的监听
-
-
-
-
-
-
with 方法总结
- 获取requestManager
- 通过绑定无界面Fragment ,通过ActivityFragmentLifecycle 来完成生命周期监听
- 初始化glide
- glide初始化的时候 注册了一系列的解码器和转码器
Load(uri)
-
load方法参数并不只有uri ,同样的load 也对应多个重载方法,当然也对应不同参数如下图所示
-
下面我们看其中一种重载方法
-
/** * 返回一个requestBuilder来加载给定地址的图片 */ public DrawableTypeRequest<String> load(String string) { return (DrawableTypeRequest<String>) fromString().load(string); } // 调用了fromString // 返回使用了来自String 类型的 requestBuilder public DrawableTypeRequest<String> fromString() { return loadGeneric(String.class); } // 调用loadGeneric private <T> DrawableTypeRequest<T> loadGeneric(Class<T> modelClass) { // 创建ModelLoader 用于加载图片 // ModeLoader 作用就是从数据源中获取原始数据 // 这里数据来源就是图片的inputStream Glide将其封装成了data ModelLoader<T, InputStream> streamModelLoader = Glide.buildStreamModelLoader(modelClass, context); ModelLoader<T, ParcelFileDescriptor> fileDescriptoModelLoader = Glide.buildFileDescriptorModelLoader(modelClass, context); // 生成 DrawableTypeRequest return optionsApplier.apply( new DrawableTypeRequest<T>(modelClass, streamModelLoader, fileDescriptorModelLoader, context, glide, requestTracker, lifecycle, optionsApplier)); } //buildStreamModelLoader /** * 为给定模型构建ModelLoader的方法,这里传递的是String对应使用注册工厂生InputStream。 */ public static <T> ModelLoader<T, InputStream> buildStreamModelLoader(Class<T> modelClass, Context context) { return buildModelLoader(modelClass, InputStream.class, context); } //buildModelLoader /** *使用注册的 ModelLoaderFactory 为给定模型类构建一个 link ModelLoader *在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); }
-
上面代码执行完成最终返回一个 DrawableTypeRequest
-
DrawableTypeRequest 是什么
-
//一个用于创建加载请求的类,直接加载GIF或bitmap public class DrawableTypeRequest<ModelType> extends DrawableRequestBuilder<ModelType> { private final ModelLoader<ModelType, InputStream> streamModelLoader; private final ModelLoader<ModelType, ParcelFileDescriptor> fileDescriptorModelLoader; private final RequestManager.OptionsApplier optionsApplier; // 以bitmap格式进行加载 public BitmapTypeRequest<ModelType> asBitmap() { return optionsApplier.apply(new BitmapTypeRequest<ModelType>(this, streamModelLoader, fileDescriptorModelLoader, optionsApplier)); } //以gif 进行加载 public GifTypeRequest<ModelType> asGif() { return optionsApplier.apply(new GifTypeRequest<ModelType>(this, streamModelLoader, optionsApplier)); }
-
由注释可知是一个用于创建加载请求的类,直接加载GIF或bitmap
-
DrawableTypeRequest 存在继承关系
GenericRequestBuilder
(该类保存了给glide设置的所有参数)DrawableRequestBuilder extends GenericRequestBuilder
(该类实现了对加载后的图片所能进行的所有操作方法 设置缩略图,大小,裁剪方式,优先级,等等)DrawableTypeRequest extends DrawableRequestBuilder
(该类继承DrawableRequestBuilder所以DrawableTypeRequest 具有上面两个类的所有信息)
-
-
调用
loadGeneric方法
返回DrawableTypeRequest
后又调用DrawableTypeRequest
的load
方法-
最终是调用的
GenericRequestBuilder
里面的load方法-
/** * 设置加载数据的具体模型 * 方法在target 之前至少调用一次 * @return 返回这个请求的builder 这是用的是BUidler 模式 方便链式调用 */ public GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> load(ModelType model) { this.model = model; isModelSet = true; return this; }
-
可以看到这里 执行完load方法后返回一个
GenericRequestBuilder
-
-
-
load 总结
- load 方法的作用就是获取一个
GenericRequestBuilder
对象- 创建
ModelLoader
生成DrawableTypeRequest
- 调用其
DrawableTypeRequest.load()
获取GenericRequestBuilder
- 创建
into(imageview)
-
//在DrawableRequestBuilder中 @override public Target<GlideDrawable> into(ImageView view) { return super.into(view); }
-
调用super的into方法 上面说到过 DrawableRequestBuilder继承自GenericRequestBuilder
public Target<TranscodeType> into(ImageView view) { // 判断是否主线程 非主线程 则抛出异常 Util.assertMainThread(); if (!isTransformationSet && view.getScaleType() != null) { //根据参数设置裁剪类型 switch (view.getScaleType()) { case CENTER_CROP: applyCenterCrop(); break; case FIT_CENTER: case FIT_START: case FIT_END: applyFitCenter(); break; default: } } // 调用into方法 传递 构建的目标图像Target 执行实际的图片加载操作 return into(glide.buildImageViewTarget(view, transcodeClass)); }
-
可以看到最后调用了into方法 传递了一个Target对象
-
那Target是什么
/** * Glide可以加载资源并在加载期间通知相关生命周期事件的接口。 */ public interface Target<R> extends LifecycleListener { int SIZE_ORIGINAL = Integer.MIN_VALUE; //onstart调用 void onLoadStarted(Drawable placeholder); //加载失败调用 void onLoadFailed(Exception e, Drawable errorDrawable); //当资源加载完成时将被调用的方法。 void onResourceReady(R resource, GlideAnimation<? super R> glideAnimation); //当加载被取消并释放其资源时调用。 void onLoadCleared(Drawable placeholder); //检索此目标大小的方法 void getSize(SizeReadyCallback cb); //设置此目标的当前请求,不应在Glide之外调用 void setRequest(Request request); //获取此目标当前的请求 Request getRequest(); }
- target 是个接口 继承LifecycleListener,内含加载资源以及生命周期监听方法
- 其有三个实现类 上面创建的也就是下面这几个实现类
- GlideDrawableImageViewTarget
- BitmapImageViewTarget
- DrawableImageViewTarget
-
如何创建Target
-
通过
glide.buildImageViewTarget(view, transcodeClass)
-
//负责为给定对象生产正确类型的Target的工厂 public class ImageViewTargetFactory { @SuppressWarnings("unchecked") //根据不同的clazz 返回不同的目标图像target对象 默认是GlideDrawableImageViewTarget 调用了asbitmap就是返回BitmapImageViewTarget public <Z> Target<Z> buildTarget(ImageView view, Class<Z> clazz) { if (GlideDrawable.class.isAssignableFrom(clazz)) { return (Target<Z>) new GlideDrawableImageViewTarget(view); } 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 { throw new IllegalArgumentException("Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)"); } } }
-
通过工厂方法传递进去view 和类型 根据类型生成对应的Target
-
-
-
super.into() 方法中的into方法 最终into方法
-
注释说了 该方法执行了图片加载的过程
-
public <Y extends Target<TranscodeType>> Y into(Y target) { Util.assertMainThread(); if (target == null) { throw new IllegalArgumentException("You must pass in a non null Target"); } if (!isModelSet) { throw new IllegalArgumentException("You must first set a model (try #load())"); } // 获取以前的 request 不为空则清空 Request previous = target.getRequest(); if (previous != null) { previous.clear(); requestTracker.removeRequest(previous); //内部调用 REQUEST_POOL.offer(this);方法,将请求放入请求池以供复用 previous.recycle(); } // 根据target 生成 request Request request = buildRequest(target); // 并设置给target target.setRequest(request); //添加生命周期监听 lifecycle.addListener(target); // 执行request requestTracker.runRequest(request); return target; }
-
into总结
-
根据设置参数选定图片裁剪类型
-
根据传递的图像类型生成对应的target ,调用into方法
-
根据target 构建request,并添加生命周期监听
-
通过请求追踪器(requestTracker)来运行request,完成图像加载
整体流程总结
- 调用with方法生成RequestManager
- 在生成过程中创建了一个RequestManagerFragment 来绑定声明周期
- 同时完成了Glide的初始化
- 调用了Load 方法 生成了GenericRequestBuilder
- 创建modelLoader 生成了GenericRequestBuilder并返回
- 调用into方法 去执行图片加载请求
- 根据设置参数选定图片裁剪类型
- 根据图片类型生成Target,调用into方法传递target
- 根据target生成了request
- 给target 绑定声明周期
- 通过请求追踪器(requestTracker)来执行request
- 请求执行流程分析请看Glide(三)图片请求执行过程