本篇将分析源码Glide.with()方法
Glide源码剖析-with
将分析源码Glide.with()
在大多数情况下,我们使用Glide
进行图片加载无非就是下面一句话
1 | #Activity |
可以见得Glide
帮我们在背后完成了海量的操作,所以下面我们将先按照使用者的角度来进行剖析
with()
1 | Glide.with(this) |
with()
是Glide
中的一组静态方法。为什么说是一组呢,因为它有很多个重载方法。在我们日常使用中,我们经常性的会往with()
里传递Activity
,有时也会传递Fragment
。所以Glide.with()
是一组静态方法
1 | #Glide |
上述代码是精简过之后的代码。可以见得虽然往里面传递了不同的参数,但最终都还是指向了getRetriever().get()
,那接下来就先看看getRetriever()
是个什么方法把
getRetriever()
1 | #Glide |
getRetriever()的代码不多。我们可以简单分析以下
Preconditions.checkNotNull()
Preconditions.checkNotNull():就是个判空处理,它接收2个参数。第一个就是需要判空的对象,第二个则是如果为空则会抛出的异常信息
- 使用优势
- 节省时间
- 简单使用,如果全部手写,可能需要写十几处判空的逻辑,还要处理异常
- 适用于空指针异常处理
- 使用优势
Glide.get().getRequestManagerRetriever()
这里可以看出先调用了
Glide.get()
在调用getRequestManagerRetriever
()获取RequestManagerRetriever
对象。那么就先看一下Glide.get()
方法把Glide.get()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#Glide
// Double checked locking is safe here.
public static Glide get( Context context){
if (glide == null) {
GeneratedAppGlideModule annotationGeneratedModule =
getAnnotationGeneratedGlideModules(context.getApplicationContext());
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context, annotationGeneratedModule);
}
}
}
return glide;
}就是单例模式下获取本身。至于是如何进行构造的我们先不用理会,这里就只用明白就是获取一个自己出来即可
那剩下的就只有
getRequestManagerRetriever
()了getRequestManagerRetriever()
1
2
3
4
5
6
7#Glide
private final RequestManagerRetriever requestManagerRetriever;
...
public RequestManagerRetriever getRequestManagerRetriever() {
return requestManagerRetriever;
}代码啥也没做,就是返回了个
RequestManagerRetriever
回来。至于它是在哪被初始化的,我们先也不展开了
回到Glide.with()
我们梳理一遍,with()
内部先调用了getRetriever()
去获取RequestManagerRetriever
,在调用了.get()
方法,相当于是直接调用了RequestManagerRetriever.get()
方法。所以说最终还是调用的是RequestManagerRetriever.get()
方法
那我们也就只能继续去查看RequestManagerRetriever.get()
方法了
RequestManagerRetriever
1 | #RequestManagerRetriever |
我们一个一个分析
方法一开始就先进行了判空处理
之后会判断当前是否处于主线程中和传入进来的
context
是否是Application
- 如果任意一个条件不满足,则会直接调用getApplicationManager()
接下就只有三种情况:
- 第一种就是传入进来的context是FragmentActivity,那么会返回get((FragmentActivity) context)
- 第二种就是传入进来的context是Activity,那么会返回get((Activity) context)
- 最后一种就是传入进来的context是属于ContextWrapper,那么会返回get(((ContextWrapper) context).getBaseContext())
ContextWrapper是继承于Context,而Activity、Service、Application也都是ContextWrapper的直接或间接子类
所以说RequestManagerRetriever.get()
方法会根据传递进来的context
类型来返回不同的RequestManager
,那就继续看看get()
方法把
get()
这里就先以参数为FragmentActivity
作为例子,别的都大同小异
1 | #RequestManagerRetriever |
一开始就直接判断当前是否处于后台线程,是的话就直接返回
get(activity.getApplicationContext())
1
2
3if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
}Util.isOnBackgroundThread():判断当前线程是否是后台线程,是返回true,不是返回false
判断传入进来的
activity
是否已经被销毁1
assertNotDestroyed(activity);
assertNotDestroyed
1
2
3
4
5
6
7#RequestManagerRetriever
private static void assertNotDestroyed( Activity activity){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && activity.isDestroyed()) {
throw new IllegalArgumentException("You cannot start a load for a destroyed activity");
}
}就判断一下当前的SDK是否大于等于17和传入进来的
activity
是否被销毁Build.VERSION_CODES.JELLY_BEAN_MR1:API 17
获取当前传入
activity
的FragmentManager
1
FragmentManager fm = activity.getSupportFragmentManager();
最后调用
supportFragmentGet()
,返回RequestManager
出去。😔还是得继续看下去,看看是如何返回RequestManager
RequestManager
这里就是重头戏了
1 | #RequestManagerRetriever |
首先第八行获取了一个SupporRequestManagerFragment,这其实是一个隐形的Fragment
1
SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint);
通过参数FragmentManager和Fragment(可空)来创建一个隐形的Fragment
这里创建一个隐形的Fragment的意图就是,想通过添加一个隐形的Fragment到Activity中去,来监听Fragment的生命周期,便于控制加载
因为Fragment的生命周期是跟随着Activity的,所以可以根据这个方法来监听到Activity的生命周期
下面又通过刚获取的Fragment又获取到了RequestManager
1
RequestManager requestManager = current.getRequestManager();
RequestManager:其实就是一个生命周期管理类,用来判断当前的生命周期来选择是否继续加载图片
到这里为止,Glide就可以根据这个 Fragment 的生命周期进行请求管理了。
但是如果是第一次,那么获取到的RequestManager会为空,就需要继续判空处理,如果刚刚current.getRequestManager()获取为空,则重新创建一个RequsetManager
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15if (requestManager == null) {
// Factor out this Glide.get() call.
Glide glide = Glide.get(context);
// 这有点小技巧,我们要启动RequestManager,但不是
// 相应的生命周期。 启动RequestManager是安全的,但是启动
// 生命周期可能会触发内存泄漏
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
if (isParentVisible) {
requestManager.onStart();
}
// 将创建好的requestManager添加到SupportRequestManagerFragment 上去
current.setRequestManager(requestManager);
}上述代码中,又重新获取了一次
Glide
单例,并通过Fractory
工厂类来构建RequestManager
,构建需要三个参数- Glide实例
- 这里的 current.getGlideLifecycle() 就是getSupportRequestManagerFragment中实例化的 ActivityFragmentLifecycle。这样 RequestManager 就与 ActivityFragmentLifecycle 进行了关联
- Context
创建完
RequestManager
之后,就根据传递进来的isParentVisible
来通知requestManager
是否开始isParentVisible:字面意思就是之前传递进来的Fragment Activity是否显示
最后就是将
RequestManager
设置到SupportRequestManagerFragment
中1
current.setRequestManager(requestManager);
getApplicationContext()
接下来在看一个Application的情况,因为大体上就可以分为两种,context是Application和context不是Application
先放出代码
1 | #RequestManagerRetriever |
总体上于非Application的差不了多少,不过我们也还是继续分析
还是和之前一样,先使用传递进来的context去获取到Glide,然后通过Glide去创建Request Manager
只不过在
getApplicationManager()
这里,通过Factory创建Request Manager的参数可不一样。在这里第一个参数还是Glide,但是第二个参数就变成了ApplicationLifecycle()
,之前是传入Fragment的getGlideLifecycle()
也就是Fragment的生命周期1
2
3
4
5
6
7
8
9
10
11class ApplicationLifecycle implements Lifecycle {
public void addListener( LifecycleListener listener){
listener.onStart();
}
public void removeListener( LifecycleListener listener){
// Do nothing.
}
}可以看出
ApplicationLifecycle
是空实现,也就是说这里没有专门做生命周期的处理, 因为 Application 对象的生命周期即为应用程序的生命周期,所以在这里图片请求的生命周期是和应用程序同步的。
总结
所以说,Glide.with()
就是根据传递进来的context是什么它就会返回什么样的Request Manager出去,至于Request Manager内部就是创建了一个隐形的Fragment上去,通过这个隐形的Fragment来监听Activity的生命周期变化
也可以说是Glide为了能够自动的配合生命周期来控制图片的加载和暂停,所以才想出判断传入进来的Context是否是Application来考虑是通过一个隐形的Fragment来感知Activity的生命周期还是直接使用ApplicationLifecycle