Glide源码分析
一、现状
以下为一次Glide图片加载典型用法,会将所需相关配置写入 requestOptions
对象,通过 setDefaultRequestOptions
方法写入自定义配置。
RequestOptions requestOptions =
RequestOptions.skipMemoryCacheOf(true).diskCacheStrategy(DiskCacheStrategy.NONE).dontAnimate()
.dontTransform();
if (circleImg) {
requestOptions = requestOptions.transform(new CircleCrop());
}
if (placeHolder > 0) {
requestOptions = requestOptions.placeholder(placeHolder);
}
if (errorHolder > 0) {
requestOptions = requestOptions.error(errorHolder);
}
if (roundRadius > 0f) {
requestOptions = requestOptions.transform(new CenterCrop(),
new RoundedCorners(ScreenUtil.dp2px(context, roundRadius)));
}
Glide.with(context)
.setDefaultRequestOptions(requestOptions)
.load(uri)
.addListener(new RequestListener<Drawable>() {})
.into(imageView);
二、存在问题
当使用Glide进行图片加载时,若没有调用过 setDefaultRequestOptions
进行配置,可能存在将其他地方配置加载过来的情况,造成错乱。
三、原因分析
根据方法定义,初步判定是由于 setDefaultRequestOptions
存在持久化问题,在设置过一次后将会在后续操作中持续 生效,直至下一次重新调用。
四、源码分析
4.1 Glide.with(context)
初始化入口方法,返回值 RequestManager
public static RequestManager with(@NonNull Context context) {
return getRetriever(context).get(context);
}
Glide#getRetriever 返回值 RequestManagerRetriever
@NonNull
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
// Context could be null for other reasons (ie the user passes in null), but in practice it will
// only occur due to errors with the Fragment lifecycle.
Preconditions.checkNotNull(
context,
"You cannot start a load on a not yet attached View or a Fragment where getActivity() "
+ "returns null (which usually occurs when getActivity() is called before the Fragment "
+ "is attached or after the Fragment is destroyed).");
return Glide.get(context).getRequestManagerRetriever();
}
Glide.get 单例方法 返回值 Glide
@NonNull
public static Glide get(@NonNull Context context) {
if (glide == null) {
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context);
}
}
}
return glide;
}
小结
Glide (singleInstance) -> RequestManagerRetriever -> RequestManager
4.2 Glide 初始化
private static void initializeGlide(@NonNull Context context) {
initializeGlide(context, new GlideBuilder());
}
private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
Context applicationContext = context.getApplicationContext();
// ..........此处省略部分代码............
RequestManagerRetriever.RequestManagerFactory factory =
annotationGeneratedModule != null
? annotationGeneratedModule.getRequestManagerFactory() : null;
builder.setRequestManagerFactory(factory);
// ..........此处省略部分代码............
Glide glide = builder.build(applicationContext);
// ..........此处省略部分代码............
Glide.glide = glide;
}
4.3 GlideBuilder 初始化
public final class GlideBuilder {
private RequestOptions defaultRequestOptions = new RequestOptions();
@NonNull
public GlideBuilder setDefaultRequestOptions(@Nullable RequestOptions requestOptions) {
this.defaultRequestOptions = requestOptions;
return this;
}
Glide build(@NonNull Context context) {
// ..........此处省略部分代码............
// 此处 RequestManagerRetriever 初始化
RequestManagerRetriever requestManagerRetriever =
new RequestManagerRetriever(requestManagerFactory);
return new Glide(
context,
engine,
memoryCache,
bitmapPool,
arrayPool,
// 此处 requestManagerRetriever 赋值
requestManagerRetriever,
connectivityMonitorFactory,
logLevel,
// 此处 defaultRequestOptions 赋值
defaultRequestOptions.lock(),
defaultTransitionOptions,
defaultRequestListeners,
isLoggingRequestOriginsEnabled);
}
}
小结
Glide 通过 GlideBuilder 进行初始化,并且在初始化时会为 RequestOptions
进行赋值,而赋值的 RequestOptions
对象在 GlideBuilder中通过无参构造被初始化,可判定该对象为初始默认配置。
RequestManagerRetriever 通过 GlideBuilder 进行初始化,并且赋值给Glide。
4.4 RequestManagerRetriever
Glide.get(context).getRequestManagerRetriever()
public class Glide implements ComponentCallbacks2 {
private final RequestManagerRetriever requestManagerRetriever;
/**
* Internal method.
*/
@NonNull
public RequestManagerRetriever getRequestManagerRetriever() {
return requestManagerRetriever;
}
}
4.5 RequestManager
RequestManagerRetriever#get(Context)
@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)) {
// 通过Activity添加Fragment 获取lifecycler 并且初始化 RequestManager
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());
}
}
// 初始化不含 lifecycler 的 RequestManager 单例
return getApplicationManager(context);
}
@NonNull
public RequestManager get(@NonNull FragmentActivity activity) {
// 后台线程使用applicationContext
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
FragmentManager fm = activity.getSupportFragmentManager();
return supportFragmentGet(
activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
}
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
private static void assertNotDestroyed(@NonNull 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");
}
}
RequestManagerRetriever#getSupportRequestManagerFragment
@NonNull
private SupportRequestManagerFragment getSupportRequestManagerFragment(
@NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
SupportRequestManagerFragment current =
(SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
if (current == null) {
current = pendingSupportRequestManagerFragments.get(fm);
if (current == null) {
current = new SupportRequestManagerFragment();
current.setParentFragmentHint(parentHint);
if (isParentVisible) {
current.getGlideLifecycle().onStart();
}
pendingSupportRequestManagerFragments.put(fm, current);
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
小结
-
在Activity下,则创建Fragment,并使用Fragment创建的RequestManager,每个Activity存在且仅存在一个实例。
-
后台线程及非ActivityContext,使用统一的RequestManager公用实例。
意义
- 获取Lifecycle
4.6 初始化RequestManager
@NonNull
private RequestManager supportFragmentGet(@NonNull Context context, @NonNull androidx.fragment.app.FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
SupportRequestManagerFragment current = this.getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
RequestManager requestManager = current.getRequestManager();
if (requestManager == null) {
Glide glide = Glide.get(context);
requestManager = this.factory.build(glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
current.setRequestManager(requestManager);
}
return requestManager;
}
// Our usage is safe here.
@SuppressWarnings("PMD.ConstructorCallsOverridableMethod")
RequestManager(
Glide glide,
Lifecycle lifecycle,
RequestManagerTreeNode treeNode,
RequestTracker requestTracker,
ConnectivityMonitorFactory factory,
Context context) {
// ..........此处省略部分代码............
setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());
glide.registerRequestManager(this);
}
protected synchronized void setRequestOptions(@NonNull RequestOptions toSet) {
requestOptions = toSet.clone().autoClone();
}
关键代码:setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());
public final class GlideBuilder {
private RequestOptions defaultRequestOptions = new RequestOptions();
@NonNull
Glide build(@NonNull Context context) {
return new Glide(
...
defaultRequestOptions.lock(),
...);
}
}
小结
RequestManager初始化时,会将Glide中的初始RequestOptions进行克隆,并赋值给RequestManager。
4.7 RequestBuilder
由上述可知,Glide的结构关系如下,Glide -> RequestManagerRetriever -> RequestManager
其中Glide、RequestManagerRetriever为全局单例
RequestManager为局部单例
而实际完成一次图片加载流程最终则需要用到RequestBuilder,以 load(String)
为例:
public RequestBuilder<Drawable> load(@Nullable String string) {
return asDrawable().load(string);
}
public RequestBuilder<Drawable> asDrawable() {
return as(Drawable.class);
}
public <ResourceType> RequestBuilder<ResourceType> as(
@NonNull Class<ResourceType> resourceClass) {
return new RequestBuilder<>(glide, this, resourceClass, context);
}
protected RequestBuilder(
@NonNull Glide glide,
RequestManager requestManager,
Class<TranscodeType> transcodeClass,
Context context) {
this.glide = glide;
this.requestManager = requestManager;
this.transcodeClass = transcodeClass;
this.context = context;
this.transitionOptions = requestManager.getDefaultTransitionOptions(transcodeClass);
this.glideContext = glide.getGlideContext();
initRequestListeners(requestManager.getDefaultRequestListeners());
// 从requestManager继承requestOptions
apply(requestManager.getDefaultRequestOptions());
}
public T apply(@NonNull BaseRequestOptions<?> o) {
if (isAutoCloneEnabled) {
return clone().apply(o);
}
BaseRequestOptions<?> other = o;
if (isSet(other.fields, SIZE_MULTIPLIER)) {
sizeMultiplier = other.sizeMultiplier;
}
if (isSet(other.fields, USE_UNLIMITED_SOURCE_GENERATORS_POOL)) {
useUnlimitedSourceGeneratorsPool = other.useUnlimitedSourceGeneratorsPool;
}
...
fields |= other.fields;
options.putAll(other.options);
return selfOrThrowIfLocked();
}
// RequestBuilder 继承自BaseRequestOptions
public class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBuilder<TranscodeType>>
implements Cloneable{}
小结
- 每一次请求会新建一个
RequestBuilder
RequestBuilder
在初始化时使用apply()
从RequestManager
读取RequestOptions
配置,且不会改变母体值。RequestBuilder
继承自BaseRequestOptions
五、结论
- 通过Activity Context 发起 Glide 事件,且当前处于主线程时,使用
setDefaultRequestOptions
会在当前Activity长期生效,直至下次重新赋值 - 通过非Activity Context发起或者当前处于子线程时,使用
setDefaultRequestOptions
会在全局长期生效,直至下次重新赋值 - 通过
apply(BaseRequestOptions)
设置,仅对当前本次加载生效 - 如果同时设置
setDefaultRequestOptions
和apply(BaseRequestOptions)
,先生效前者,然后在此基础上生效后者的改动项