携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第7天,点击查看活动详情
基本用法
Glide最基本的用法如下:
Glide.with(context)
.load(url)
.into(imageView)
本文就从这三个方法去学习Glide的源码。(挖个坑,以后补一下其他各种API的实现)
PS:本文基于4.13.2版本的Glide源码。
废话不多说直接开始!
with
首先with传入的是Context(具体分三种情况:Application、Fragment、Activity),返回的是RequestManager。暂时还不用了解这个RequestManager是什么,只要知道它是用来调用load()就可以了。
with的其中一个重载方法如下:
@NonNull
public static RequestManager with(@NonNull Context context) {
return getRetriever(context).get(context);
}
正如上面所说,with传入的参数可以是Application、Fragment、Activity,所以with是有好几个对应的重载方法的。但是都跟上面这个大差不差,其实在这里还没有体现出差别。
接着看这个getRetriever的方法。Retriever的中文意思是猎犬,诶那我们肯定不能理解为猎犬是吧。我个人的理解是跟Fetcher的意思差不多,一个帮你到指定地方取某样东西回来的“人”。既然with的返回值是RequestManager,那“某样东西”自然就是RequestManager了。getRetriever很简单,如下:
@NonNull
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
//省略
return Glide.get(context).getRequestManagerRetriever();
}
Glide.get方法是构建一个Glide实例,getRequestManagerRetriever则是简单地返回一个Glide的内部变量,所以说重点就在Glide.get里面。
public static Glide get(@NonNull Context context) {
if (glide == null) {
GeneratedAppGlideModule annotationGeneratedModule =
getAnnotationGeneratedGlideModules(context.getApplicationContext());
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context, annotationGeneratedModule);
}
}
}
return glide;
}
可以很明显地看到,这是一个双重检查的懒汉式单例构建形式。换言之Glide的实例是一个单例。这个GeneratedAppGlideModule貌似是用来定制化Glide功能的,我也不大看得明白,就不管了hhh!
继续追踪checkAndInitializeGlide。里面再次检查了一下初始化情况,接着调用initializeGlide,我们直接看这个方法吧!
private static void initializeGlide(
@NonNull Context context,
@NonNull GlideBuilder builder,
@Nullable GeneratedAppGlideModule annotationGeneratedModule) {
Context applicationContext = context.getApplicationContext();
//省略,GlideModule相关逻辑,无视无视。
RequestManagerRetriever.RequestManagerFactory factory =
annotationGeneratedModule != null
? annotationGeneratedModule.getRequestManagerFactory()
: null;
builder.setRequestManagerFactory(factory);
//省略,GlideModule相关逻辑,无视无视。
Glide glide = builder.build(applicationContext);
//省略,GlideModule相关逻辑,无视无视。
applicationContext.registerComponentCallbacks(glide);
Glide.glide = glide;
}
除去GlideModule之外的逻辑大概分成三步:
- 获取RequestManager的Factory。
- 将Factory设给Glide的Builder并构建Glide实例。
- 向Application注册ComponentCallback(Glide实现)
第一步,获取RequestManager的Factory。判读是否有GlideModule,没有就传null。我们没用用到GlideModule那就应该是null。
第二步,重点在Builder的build方法中:
@NonNull
Glide build(@NonNull Context context) {
//省略一大堆与配置相关的初始化代码,缓存、动画、bitmap复用池等等
GlideExperiments experiments = glideExperimentsBuilder.build();
RequestManagerRetriever requestManagerRetriever =
new RequestManagerRetriever(requestManagerFactory, experiments);
return new Glide(
context,
engine,
memoryCache,
bitmapPool,
arrayPool,
requestManagerRetriever,
connectivityMonitorFactory,
logLevel,
defaultRequestOptionsFactory,
defaultTransitionOptions,
defaultRequestListeners,
experiments);
}
GlideExperiments我看了下注释,貌似是用来跟踪实验性API过程的东西(也就是说不用管它)。
终于到了构建RequestManagerRetriever了,继续跟踪。
public RequestManagerRetriever(
@Nullable RequestManagerFactory factory, GlideExperiments experiments) {
this.factory = factory != null ? factory : DEFAULT_FACTORY;
handler = new Handler(Looper.getMainLooper(), this);
frameWaiter = buildFrameWaiter(experiments);
}
由于我们传入的Factory是null,所以这里将会使用DEFAULT_FACTORY。大胆猜测一下,RequestManagerRetriever获取RequestManager的方式就是从这个DEFAULT_FACTORY生产出来的。
接着还创建了一个handler用于接收一些指令,与后面感知生命周期的逻辑有关。
最后还build了一个FrameWaiter,因为传入的是GlideExperiments,所以应该是跟实验性API有关的,这里也不管了。
上面这段代码最重要的地方就是这个DEFAULT_FACTORY,继续看看是啥玩意。
private static final RequestManagerFactory DEFAULT_FACTORY =
new RequestManagerFactory() {
@NonNull
@Override
public RequestManager build(
@NonNull Glide glide,
@NonNull Lifecycle lifecycle,
@NonNull RequestManagerTreeNode requestManagerTreeNode,
@NonNull Context context) {
return new RequestManager(glide, lifecycle, requestManagerTreeNode, context);
}
};
可以看出来,DEFAULT_FACTORY就是RequestManagerFactory的一个匿名实现,build方法返回一个RequestManager。
这里用图的方式复习一下:
sequenceDiagram
Glide->>Glide:with()
Glide->>Glide:getRetriever()
Glide->>Glide:get()
Glide->>GlideBuilder:new
GlideBuilder->>GlideBuilder:build()
GlideBuilder->>RequestManagerRetriever:new
RequestManagerRetriever->>RequestManagerRetriever:DEFAULT_FACTORY
RequestManagerRetriever->>GlideBuilder:requestManagerRetriever()
GlideBuilder->>Glide:glide
Glide->>Glide:getRequestManagerRetriever()
这时候RequestManagerRetriever已经构造出来了,让我们回头再看回with方法,这里再贴一遍代码,免得往上翻了。
@NonNull
public static RequestManager with(@NonNull Context context) {
return getRetriever(context).get(context);
}
既然getRetriever已经构建好RequestManagerRetriever了,那就看看RequestManagerRetriever.get吧!
@NonNull
public RequestManager get(@NonNull 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
&& ((ContextWrapper) context).getBaseContext().getApplicationContext() != null) {//④
return get(((ContextWrapper) context).getBaseContext());
}
}
return getApplicationManager(context);//⑤
}
get有好几个重载方法,上面贴出来的则是负责根据Context的具体类型调用不同的get方法。
首先是①处判断,在主线程调用并且传入的Context为非Application。
然后是②处判断,传入Context是FragmentActivity。
接着是③处判断,传入Context为Activity。
跟着是④处判断,传入的Context是ContextWrapper并且Application不为空。
最后是⑤处判断,以上判断都不符合。
其中FragmentActivity和Activity的区别判断应该是为了向低版本兼容,这里就只讨论Activity的情况。
如果传入的Context为Activity,对应的get如下:
@NonNull
public RequestManager get(@NonNull Activity activity) {
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else if (activity instanceof FragmentActivity) {
return get((FragmentActivity) activity);
} else {//①
assertNotDestroyed(activity);
frameWaiter.registerSelf(activity);
android.app.FragmentManager fm = activity.getFragmentManager();
return fragmentGet(activity, fm, null, isActivityVisible(activity));
}
}
重点看①处后的代码,一行行来看。
assertNotDestroyed用于判读传入的Acitivity是否已销毁,已销毁则抛出异常。
framWaiter忽略。
获取FragmentManager。
调用fragmentGet方法:
@NonNull
private RequestManager fragmentGet(
@NonNull Context context,
@NonNull android.app.FragmentManager fm,
@Nullable android.app.Fragment parentHint,
boolean isParentVisible
) {
RequestManagerFragment current = getRequestManagerFragment(fm, parentHint);
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
Glide glide = Glide.get(context);
requestManager = factory.build(
glide,
current.getGlideLifecycle(),
current.getRequestManagerTreeNode(),
context);
if (isParentVisible) {
requestManager.onStart();
}
current.setRequestManager(requestManager);
}
return requestManager;
}
首先调用了getRequestManagerFragment获取了一个RequestManagerFragment。RequestManagerFragment实际上就是一个Fragment的子类。它的用途就是感知Activity的生命周期。通过目标Activity的FragmentManager构建一个无界面的Fragment,并且由于Fragment与Activity的生命周期是同步的,所以就能感知目标Activity的生命周期变化。刚刚上面那个RequestManagerRetriever里面的handle就是用来接受移除这个Fragment的指令的。
通过观察不同的RequestManager.get的重载方法,发现不管传入的是Activity还是Fragment,最终都是通过添加一个无界面的Fragment去感知生命周期的。
由于第一次创建这个Fragment,所以不能获取到RequestManager。代码走到了获取RequestManager里。可以看到是通过调用RequestManagerFactory.build来构建的,从之前的分析我们知道这个Factory就是DEFAULT_FACTORY。
后半部分的流程也用图的方式复习一下:
sequenceDiagram
RequestManagerRetriever->>RequestManagerRetriever:get()
RequestManagerRetriever->>RequestManagerRetriever:fragmentGet()
RequestManagerRetriever->>RequestManagerFragment:getRequestManagerFragment()
RequestManagerFragment->>RequestManagerRetriever:fragment
RequestManagerRetriever->>RequestManagerFactory:build()
RequestManagerFactory->>RequestManagerRetriever:requestManager
至此,with的工作就已经完成了,我们也获得了RequestManager。下一篇我们再来分析RequestManager以及它的load方法。