一直在使用Glide进行图片的加载显示,想看看Glide的源码实现是如何做的,终于有时间阅读了下源码,写下来就当做个笔记,也分享给大家学习下。如果有错误,欢迎各位指正。
我们要加载并显示一张图片只需要一行代码,如下所示:
Glide.with(Context).load(source).into(target);
具体Glide中做了什么操作,怎么操作。我们进一步了解下。
用添加依赖的方式将Glide引入到项目中的,在Android Studio中就可以直接进行查看。
也可以在GitHub将源码下载下来,分析用的源码是4.8.0,下载点这里:https://github.com/bumptech/glide/releases/tag/v4.8.0
按照加载步骤,就是三步:先with(),再load(),最后into()。那么我们开始一步步阅读源码,先从with()看起。
public static RequestManager with(@NonNull Context context) {
return getRetriever(context).get(context);
}
public static RequestManager with(@NonNull Activity activity) {
return getRetriever(activity).get(activity);
}
public static RequestManager with(@NonNull FragmentActivity activity) {
return getRetriever(activity).get(activity);
}
public static RequestManager with(@NonNull Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}
public static RequestManager with(@NonNull android.app.Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}
public static RequestManager with(@NonNull View view) {
return getRetriever(view.getContext()).get(view);
}
with() 是一组重载的静态方法,每个with()方法传入的参数不同,有fragment、activity、context三种参数。
with() 返回的是RequestManager,所以应该可以猜到,接下来的load()的操作肯定是在RequestManager 中进行。
with() 内部调用了getRetriever(),紧接着又调用了get方法。一般,单例模式都是用get方法返回唯一实例的,所以可以想到是在get中返回了RequestManager对象 。
那getRetriever()中的逻辑是什么?又做了什么操作?
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
...
return Glide.get(context).getRequestManagerRetriever();
}
在getRetriever方法内部调用Glide的get方法返回单例对象,再调用Glide的getRequestManagerRetriever方法,返回RequestManagerRetriever。我们进Glide的get中看具体做了什么操作。
/**
public static Glide get(@NonNull Context context) {
if (glide == null) {
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context);
}
}
}
return glide;
}
在get方法内部采用双重锁检测机制(DCL,单例模式的实现方法之一)检查并初始化Glide后返回glide唯一实例,glide变量在声明的时候用是volatile关键字修饰。可知上一步中getRequestManagerRetriever是在Glide中获取RequestManagerRetriever。重点来了,看看如何进行检查和初始化Glide的。
private static void checkAndInitializeGlide(@NonNull Context context) {
// In the thread running initGlide(), one or more classes may call Glide.get(context).
// Without this check, those calls could trigger infinite recursion.
if (isInitializing) {
throw new IllegalStateException("You cannot call Glide.get() in registerComponents(),"
+ " use the provided Glide instance instead");
}
isInitializing = true;
initializeGlide(context);
isInitializing = false;
}
在方法内调用initializeGlide(context),在initializeGlide(context)中又调用了initializeGlide(context, new GlideBuilder())。
@SuppressWarnings("deprecation")
private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
Context applicationContext = context.getApplicationContext();
GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules();
List manifestModules = Collections.emptyList();
if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
manifestModules = new ManifestParser(applicationContext).parse();
}
...
移除相同的GlideModule
...
RequestManagerRetriever.RequestManagerFactory factory =
annotationGeneratedModule != null
? annotationGeneratedModule.getRequestManagerFactory() : null;
...
设置Glide Builder
...
Glide glide = builder.build(applicationContext);
...
//注册组件
...
//注册内存优化的系统回调
applicationContext.registerComponentCallbacks(glide);
Glide.glide = glide;
}
到目前为止,glide的初始化已完成,并创建了glide唯一实例。
然后返回到上面的getRequestManagerRetriever,继续跟踪。
@NonNull
public RequestManagerRetriever getRequestManagerRetriever() {
return requestManagerRetriever;
}
拿到Glide的成员变量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) {
return get(((ContextWrapper) context).getBaseContext());
}
}
return getApplicationManager(context);
}
在这里,我们可以看到with传进来的参数派上用场了,根据context的类型走不同的分支。
如果context是null,则直接抛出异常。如果不是在主线程或者传进来的context是Application类型则返回getApplicationManager,Application对象的生命周期就是应用的生命周期,这种情况下它和应用的生命周期是同步的,在应用关闭退出的时候,Glide的加载也会自动终止。如果不是上面的情况则根据context的类型执行对应的执行get()方法。
@NonNull
public RequestManager get(@NonNull FragmentActivity activity) {
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
FragmentManager fm = activity.getSupportFragmentManager();
return supportFragmentGet(
activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
}
}
@NonNull
public RequestManager get(@NonNull Fragment fragment) {
Preconditions.checkNotNull(fragment.getActivity(),
"You cannot start a load on a fragment before it is attached or after it is destroyed");
if (Util.isOnBackgroundThread()) {
return get(fragment.getActivity().getApplicationContext());
} else {
FragmentManager fm = fragment.getChildFragmentManager();
return supportFragmentGet(fragment.getActivity(), fm, fragment, fragment.isVisible());
}
}
可以看到,如果是在后台线程中,则按Application类型处理。不管传进来是Activity还是fragment,在get方法中最终都调用了supportFragmentGet方法,
@NonNull
private RequestManager supportFragmentGet(
@NonNull Context context,
@NonNull FragmentManager fm,
@Nullable Fragment parentHint,
boolean isParentVisible) {
SupportRequestManagerFragment current =
getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
// TODO(b/27524013): Factor out this Glide.get() call.
Glide glide = Glide.get(context);
requestManager =
factory.build(
glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
current.setRequestManager(requestManager);
}
return requestManager;
}
重点来了,在supportFragmentGet方法中创建了一个没有界面的fragment,它的生命周期和context保持一致,这样context在销毁的时候,fragment可以检测到这个销毁操作,那么Glide的加载在fragment销毁的时候也会同步停止。最终返回了requestManager实例。至此with的流程走完了,与咱们开头看到的with方法返回RequestManager类型的结果是一致的。