Glide setDefaultRequestOptions 源码分析
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();@NonNullpublic 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.*/@NonNullpublic 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 并且初始化 RequestManagerif (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) {// 后台线程使用applicationContextif (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();@NonNullGlide 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继承requestOptionsapply(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),先生效前者,然后在此基础上生效后者的改动项
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
