下面來看在Glide中最簡單的圖片加載代碼
Glide.with(this)
.load("https://p.upyun.com/docs/cloud/demo.jpg")
.into(imageView);
這應(yīng)該是相對比較簡單的加載圖片的代碼了麸恍,一步步來灵巧,看代碼其實(shí)很講究耐心,有時(shí)候會(huì)遇到很多層次的調(diào)用鏈或南,這個(gè)時(shí)候其實(shí)很有必要自己畫一些圖孩等,很能幫助理清一些思路艾君。下面來看這段比較看似比較簡單的代碼采够,其實(shí)在Glide源碼中,運(yùn)用到了大量的類的設(shè)計(jì)冰垄,后面涉及的我會(huì)慢慢介紹到蹬癌。
首先簡單介紹下這個(gè)Glide類,它相當(dāng)于是整個(gè)框架的調(diào)用入口虹茶,有一點(diǎn)像外觀模式逝薪,一般很多第三方sdk都會(huì)用到這種模式,提供一個(gè)高層接口蝴罪,減少用戶的使用成本董济,對于我們第一個(gè)with方法,這個(gè)其實(shí)就是一個(gè)工廠方法要门,雖然有許多重載的形式虏肾,其實(shí)都是要?jiǎng)?chuàng)建一個(gè)RequestManager對象。下面我們來看這個(gè)
這個(gè)with方法欢搜,如下:
icon_glide_with.png
Glide#with方法有六個(gè)重載的形式封豪,但是第一部分都是調(diào)用Glide#getRetriever獲取一個(gè)RequestManagerRetriever對象,進(jìn)而調(diào)用RequestManagerRetriever#get方法最終創(chuàng)建一個(gè)RequestManager對象炒瘟。下面一個(gè)個(gè)來進(jìn)行分析吹埠。
1.Glide#with
@NonNull
public static RequestManager with(@NonNull FragmentActivity activity) {
return getRetriever(activity).get(activity);
}
還有其他的重載形式,其實(shí)第一部分都是一樣,都是獲取他們(Actvity/View/Fragment等)的上下文缘琅,然后通過getRetriever方法去獲取一個(gè)RequestManagerRetriever對象粘都。進(jìn)而得到一個(gè)RequestManager。
2.Glide#getRetriever
@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();
}
這個(gè)方法先是進(jìn)行了context的非空檢查刷袍,然后調(diào)用Glide#get方法
3.Glide#get
@NonNull
public static Glide get(@NonNull Context context) {
if (glide == null) {
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context);
}
}
}
return glide;
}
這個(gè)方法的主要邏輯是構(gòu)建一個(gè)Glide的單例對象驯杜,初始化Glide對象時(shí),做了很多復(fù)雜的配置信息做个,包括緩存策略等等鸽心,這里我們暫時(shí)跳過,后續(xù)講到這些配置信息再詳細(xì)分析居暖,有時(shí)候顽频,看代碼要忽略其他的細(xì)節(jié),沿著一條主線走太闺,站在宏觀的視角糯景,針對具體問題再行微觀分析,往往會(huì)比較清晰省骂。這里獲取到一個(gè)Glide實(shí)例之后蟀淮,回到第2步,接下來回到Glide#getRetriever钞澳,然后是調(diào)用了Glide#getRequestManagerRetriever繼續(xù)請求怠惶。
4.Glide#getRequestManagerRetriever
@NonNull
public RequestManagerRetriever getRequestManagerRetriever() {
return requestManagerRetriever;
}
這個(gè)方法很簡單,就是返回一個(gè)RequestManagerRetriever對象轧粟,那么它是在什么時(shí)候初始化的呢策治,通過代碼分析,在Glide初始化時(shí)候兰吟,會(huì)初始化這個(gè)requestManagerRetriever對象通惫,我們暫且略過它。有了這個(gè)requestManagerRetriever對象后混蔼,回到第1步履腋,接下來會(huì)調(diào)用RequestManagerRetriever#get方法,與Glide#with對應(yīng)惭嚣,它也有6個(gè)重載的形式遵湖,均是返回一個(gè)RequestManager。
5.RequestManagerRetriever#get
icon_request_manager_retriever_get.png
雖然是有這么多重載形式料按,但都是一個(gè)平行的關(guān)系奄侠,為了理解原理,去繁為簡载矿,其實(shí)我們完全可以只分析某一個(gè)垄潮,這里我們以參數(shù)為FragmentActivity為例烹卒,畢竟項(xiàng)目中其實(shí)大多數(shù)都是使用FragmentActivity了。
@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));
}
}
這里有兩個(gè)分支弯洗,一個(gè)是ui線程旅急,一個(gè)是非ui線程,這里我們先考慮在ui線程中的情況牡整,把一條線走通藐吮,后續(xù)再來分析一些分支的情況√颖矗可以看到谣辞,在ui線程中,首先是獲取了support下面的FragmentManager對象沐扳,然后繼續(xù)調(diào)用supportFragmentGet泥从。
6.RequestManagerRetriever#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;
}
這個(gè)方法有4個(gè)參數(shù),以我們現(xiàn)在為例沪摄,parentHint為null躯嫉,isParentVisible為true。還是一個(gè)道理杨拐,我們可以假定某一種情況祈餐,便于代碼的主線分析。接下來是構(gòu)建了一個(gè)SupportRequestManagerFragment對象哄陶,它就是一個(gè)Fragment對象帆阳,其實(shí)沒有什么神秘,它里面綁定了一些Lifecycle的方法奕筐,后續(xù)我們會(huì)看到舱痘。這里其實(shí)用了一個(gè)技巧,因?yàn)槲覀兛吹嚼牒眨櫼粋€(gè)Activity的生命周期,同時(shí)又要能夠達(dá)到通用性塌碌,顯然在用戶的業(yè)務(wù)Activity中是不太可能能插入生命周期的鉤子方法渊胸,那么,作為一個(gè)框架層面的台妆,顯然要必備一些通用性才行翎猛,這里Glide是通過手動(dòng)添加一個(gè)隱藏的SupportRequestManagerFragment對象,通過監(jiān)聽它的生命周期變化而達(dá)到監(jiān)聽到宿主Activity生命周期的目的接剩,顯然切厘,這里是完全可行的方案。我們先繼續(xù)分析getSupportRequestManagerFragment這個(gè)方法的實(shí)現(xiàn)懊缺。
7.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;
}
這里沒有什么比較難的疫稿,唯獨(dú)就是有一個(gè)小技巧,為什么需要這個(gè)pendingSupportRequestManagerFragments對象,它其實(shí)是為了避免重復(fù)創(chuàng)建SupportRequestManagerFragment對象遗座,這里有兩個(gè)if檢查舀凛,初學(xué)者可能會(huì)有點(diǎn)奇怪,這是因?yàn)镕ragmentManager提交這個(gè)方法是一個(gè)消息機(jī)制觸發(fā)的形式途蒋,并不會(huì)立即的執(zhí)行猛遍,如果此時(shí)多次調(diào)用而沒有pendingSupportRequestManagerFragments的保證,是會(huì)多次建立對象的号坡。顯然添加到fm中后懊烤,就不再需要pendingSupportRequestManagerFragments,所以在下一個(gè)消息到達(dá)時(shí)候宽堆,ID_REMOVE_SUPPORT_FRAGMENT_MANAGER中及時(shí)的被移除奸晴。然后這里我們看到isParentVisible這個(gè)變量,其實(shí)是觸發(fā)Lifecycle的一些回調(diào)日麸。有了這個(gè)Fragment之后寄啼,我們繼續(xù)回到第6步的邏輯。這里就開始了RequestManager的構(gòu)造代箭,然后再設(shè)置到SupportRequestManagerFragment的成員變量requestManager中墩划。下面我們繼續(xù)分析這個(gè)RequestManager的構(gòu)造過程。這里factory的實(shí)現(xiàn)類是一個(gè)GeneratedRequestManagerFactory嗡综。
8.GeneratedRequestManagerFactory#build
@Override
@NonNull
public RequestManager build(@NonNull Glide glide, @NonNull Lifecycle lifecycle,
@NonNull RequestManagerTreeNode treeNode, @NonNull Context context) {
return new GlideRequests(glide, lifecycle, treeNode, context);
}
這個(gè)工廠方法乙帮,最終會(huì)構(gòu)建一個(gè)GlideRequests對象,至此創(chuàng)建RequestManager的任務(wù)就已經(jīng)完成极景,Glide#with方法執(zhí)行完成察净,這里我們可以看到,RequestManager對于同一個(gè)上下文來說是唯一的盼樟。下面我們繼續(xù)分析GlideRequests的load方法氢卡。
9.GlideRequests#load
@Override
@NonNull
@CheckResult
public GlideRequest<Drawable> load(@Nullable String string) {
return (GlideRequest<Drawable>) super.load(string);
}
這個(gè)很簡單,直接是調(diào)用父類的load方法晨缴。
10.RequestManager#load
@NonNull
@CheckResult
@Override
public RequestBuilder<Drawable> load(@Nullable String string) {
return asDrawable().load(string);
}
首先分析這個(gè)方法译秦,發(fā)現(xiàn)返回類型是一個(gè)RequestBuilder,顯然Glide對于請求的各種鏈?zhǔn)浇Y(jié)構(gòu)用到了Builder的設(shè)計(jì)模式击碗,以后我們會(huì)經(jīng)持玻看到各種鏈?zhǔn)降亩鄥?shù)的加載方式。下面我們繼續(xù)分析asDrawable的實(shí)現(xiàn)稍途。
11.RequestManager#asDrawable
@NonNull
@CheckResult
public RequestBuilder<Drawable> asDrawable() {
return as(Drawable.class);
}
@NonNull
@CheckResult
public <ResourceType> RequestBuilder<ResourceType> as(
@NonNull Class<ResourceType> resourceClass) {
return new RequestBuilder<>(glide, this, resourceClass, context);
}
在asDrawable方法中阁吝,繼續(xù)調(diào)用了as方法,傳入了一個(gè)Drawable.class參數(shù)械拍,接著就是調(diào)用RequestBuilder的構(gòu)造方法突勇,將參數(shù)傳入装盯。RequestBuilder中涉及到大量的圖片加載參數(shù)的設(shè)置。接下來進(jìn)入到步驟10与境,通過RequestBuilder#load傳入第一個(gè)參數(shù)验夯。
12.RequestBuilder#load
@NonNull
@Override
@CheckResult
public RequestBuilder<TranscodeType> load(@Nullable String string) {
return loadGeneric(string);
}
@NonNull
private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
this.model = model;
isModelSet = true;
return this;
}
這個(gè)方法也很簡單,只是設(shè)置了model這個(gè)屬性的值摔刁,至此挥转,load(url)方法全部結(jié)束。接下來分析最后一個(gè)重要的方法into共屈。
13.RequestBuilder#into
@NonNull
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
Util.assertMainThread();
Preconditions.checkNotNull(view);
RequestOptions requestOptions = this.requestOptions;
if (!requestOptions.isTransformationSet()
&& requestOptions.isTransformationAllowed()
&& view.getScaleType() != null) {
// Clone in this method so that if we use this RequestBuilder to load into a View and then
// into a different target, we don't retain the transformation applied based on the previous
// View's scale type.
switch (view.getScaleType()) {
case CENTER_CROP:
requestOptions = requestOptions.clone().optionalCenterCrop();
break;
case CENTER_INSIDE:
requestOptions = requestOptions.clone().optionalCenterInside();
break;
case FIT_CENTER:
case FIT_START:
case FIT_END:
requestOptions = requestOptions.clone().optionalFitCenter();
break;
case FIT_XY:
requestOptions = requestOptions.clone().optionalCenterInside();
break;
case CENTER:
case MATRIX:
default:
// Do nothing.
}
}
return into(
glideContext.buildImageViewTarget(view, transcodeClass),
/*targetListener=*/ null,
requestOptions);
}
這個(gè)方法中绑谣,設(shè)計(jì)到一個(gè)新的東西RequestOptions,主要涉及到圖片的展示拗引,這里我們也暫且跳過借宵,它有一個(gè)默認(rèn)值。transcodeClass就是我們上面?zhèn)魅氲腄rawable.class矾削,接下來分析buildImageViewTarget這個(gè)方法的實(shí)現(xiàn)壤玫。
@NonNull
public <X> ViewTarget<ImageView, X> buildImageViewTarget(
@NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {
return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
}
它的具體實(shí)現(xiàn)在ImageViewTargetFactory下,我們繼續(xù)看
public <Z> ViewTarget<ImageView, Z> buildTarget(@NonNull ImageView view,
@NonNull Class<Z> clazz) {
if (Bitmap.class.equals(clazz)) {
return (ViewTarget<ImageView, Z>) new BitmapImageViewTarget(view);
} else if (Drawable.class.isAssignableFrom(clazz)) {
return (ViewTarget<ImageView, Z>) new DrawableImageViewTarget(view);
} else {
throw new IllegalArgumentException(
"Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
}
}
可以看到這里哼凯,我們會(huì)得到一個(gè)DrawableImageViewTarget欲间,這個(gè)target特別重要。獲取到這個(gè)對象之后断部,我們繼續(xù)往下分析into方法猎贴。
private <Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener,
@NonNull RequestOptions options) {
Util.assertMainThread();
Preconditions.checkNotNull(target);
if (!isModelSet) {
throw new IllegalArgumentException("You must call #load() before calling #into()");
}
options = options.autoClone();
Request request = buildRequest(target, targetListener, options);
Request previous = target.getRequest();
if (request.isEquivalentTo(previous)
&& !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
request.recycle();
// If the request is completed, beginning again will ensure the result is re-delivered,
// triggering RequestListeners and Targets. If the request is failed, beginning again will
// restart the request, giving it another chance to complete. If the request is already
// running, we can let it continue running without interruption.
if (!Preconditions.checkNotNull(previous).isRunning()) {
// Use the previous request rather than the new one to allow for optimizations like skipping
// setting placeholders, tracking and un-tracking Targets, and obtaining View dimensions
// that are done in the individual Request.
previous.begin();
}
return target;
}
requestManager.clear(target);
target.setRequest(request);
requestManager.track(target, request);
return target;
}
前面的檢查邏輯跳過,這里我們的targetListener是null蝴光,target是一個(gè)DrawableImageViewTarget對象她渴,然后是通過buildRequest方法,創(chuàng)建了一個(gè)Request對象蔑祟〕煤模看名字可以知道,這個(gè)才是真正的請求做瞪,只有到into此時(shí)对粪,才會(huì)真正的去請求,我們先分析這個(gè)的實(shí)現(xiàn)装蓬。
14.RequestBuilder#buildRequest
private Request buildRequest(
Target<TranscodeType> target,
@Nullable RequestListener<TranscodeType> targetListener,
RequestOptions requestOptions) {
return buildRequestRecursive(
target,
targetListener,
/*parentCoordinator=*/ null,
transitionOptions,
requestOptions.getPriority(),
requestOptions.getOverrideWidth(),
requestOptions.getOverrideHeight(),
requestOptions);
}
這個(gè)方法直接是取了requestOptions的一些信息,以及transitionOptions信息纱扭,繼續(xù)往下調(diào)用牍帚。
private Request buildRequestRecursive(
Target<TranscodeType> target,
@Nullable RequestListener<TranscodeType> targetListener,
@Nullable RequestCoordinator parentCoordinator,
TransitionOptions<?, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight,
RequestOptions requestOptions) {
// Build the ErrorRequestCoordinator first if necessary so we can update parentCoordinator.
ErrorRequestCoordinator errorRequestCoordinator = null;
if (errorBuilder != null) {
errorRequestCoordinator = new ErrorRequestCoordinator(parentCoordinator);
parentCoordinator = errorRequestCoordinator;
}
Request mainRequest =
buildThumbnailRequestRecursive(
target,
targetListener,
parentCoordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
requestOptions);
if (errorRequestCoordinator == null) {
return mainRequest;
}
int errorOverrideWidth = errorBuilder.requestOptions.getOverrideWidth();
int errorOverrideHeight = errorBuilder.requestOptions.getOverrideHeight();
if (Util.isValidDimensions(overrideWidth, overrideHeight)
&& !errorBuilder.requestOptions.isValidOverride()) {
errorOverrideWidth = requestOptions.getOverrideWidth();
errorOverrideHeight = requestOptions.getOverrideHeight();
}
Request errorRequest = errorBuilder.buildRequestRecursive(
target,
targetListener,
errorRequestCoordinator,
errorBuilder.transitionOptions,
errorBuilder.requestOptions.getPriority(),
errorOverrideWidth,
errorOverrideHeight,
errorBuilder.requestOptions);
errorRequestCoordinator.setRequests(mainRequest, errorRequest);
return errorRequestCoordinator;
}
這里我們并沒有設(shè)置,直接跳過乳蛾,所以只用管mainRequest這個(gè)構(gòu)建過程暗赶,在這里鄙币,我們可以看到,Glide是支持簡單的嵌套R(shí)equest邏輯的蹂随,此時(shí)我們暫且跳過十嘿。然后是進(jìn)入buildThumbnailRequestRecursive方法。
private Request buildThumbnailRequestRecursive(
Target<TranscodeType> target,
RequestListener<TranscodeType> targetListener,
@Nullable RequestCoordinator parentCoordinator,
TransitionOptions<?, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight,
RequestOptions requestOptions) {
if (thumbnailBuilder != null) {
.....
return coordinator;
} else if (thumbSizeMultiplier != null) {
....
return coordinator;
} else {
// Base case: no thumbnail.
return obtainRequest(
target,
targetListener,
requestOptions,
parentCoordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight);
}
}
這個(gè)方法的實(shí)現(xiàn)也比較長岳锁,這里根據(jù)我們的邏輯绩衷,并沒有設(shè)置thumbnailBuilder和thumbSizeMultiplier,其實(shí)要關(guān)注的就是最后一個(gè)else邏輯激率,這樣分析其實(shí)能讓我不受分支的影響咳燕,更容易把握整體流程,呆需要深入研究thumbnai這塊時(shí)候乒躺,可以繼續(xù)去挖掘招盲。下面我們繼續(xù)看沒有thumbnail時(shí)候的邏輯,obtainRequest這個(gè)方法的實(shí)現(xiàn)嘉冒。
private Request obtainRequest(
Target<TranscodeType> target,
RequestListener<TranscodeType> targetListener,
RequestOptions requestOptions,
RequestCoordinator requestCoordinator,
TransitionOptions<?, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight) {
return SingleRequest.obtain(
context,
glideContext,
model,
transcodeClass,
requestOptions,
overrideWidth,
overrideHeight,
priority,
target,
targetListener,
requestListener,
requestCoordinator,
glideContext.getEngine(),
transitionOptions.getTransitionFactory());
}
看到這個(gè)方法的名字曹货,是不是覺得很熟悉,對讳推,我們的Handler里面就有類似的方法顶籽,這里Glide用到了享元的一種設(shè)計(jì)模式,出于對內(nèi)存的節(jié)省娜遵。接下來繼續(xù)分析obtain的實(shí)現(xiàn)蜕衡。
public static <R> SingleRequest<R> obtain(
Context context,
GlideContext glideContext,
Object model,
Class<R> transcodeClass,
RequestOptions requestOptions,
int overrideWidth,
int overrideHeight,
Priority priority,
Target<R> target,
RequestListener<R> targetListener,
RequestListener<R> requestListener,
RequestCoordinator requestCoordinator,
Engine engine,
TransitionFactory<? super R> animationFactory) {
@SuppressWarnings("unchecked") SingleRequest<R> request =
(SingleRequest<R>) POOL.acquire();
if (request == null) {
request = new SingleRequest<>();
}
request.init(
context,
glideContext,
model,
transcodeClass,
requestOptions,
overrideWidth,
overrideHeight,
priority,
target,
targetListener,
requestListener,
requestCoordinator,
engine,
animationFactory);
return request;
}
可以看到,先是從對象池里面去取设拟,有則共享慨仿,減少new對象的成本。然后調(diào)用init方法纳胧,進(jìn)行一些參數(shù)設(shè)置镰吆。最后我們看到,一個(gè)request對象的創(chuàng)建也就結(jié)束了跑慕。繼續(xù)回到主線万皿,返回到步驟13,回到into方法核行,繼續(xù)往下執(zhí)行牢硅。
15.RequestBuilder.into
private <Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener,
@NonNull RequestOptions options) {
....
Request request = buildRequest(target, targetListener, options);
Request previous = target.getRequest();
if (request.isEquivalentTo(previous)
&& !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
request.recycle();
// If the request is completed, beginning again will ensure the result is re-delivered,
// triggering RequestListeners and Targets. If the request is failed, beginning again will
// restart the request, giving it another chance to complete. If the request is already
// running, we can let it continue running without interruption.
if (!Preconditions.checkNotNull(previous).isRunning()) {
// Use the previous request rather than the new one to allow for optimizations like skipping
// setting placeholders, tracking and un-tracking Targets, and obtaining View dimensions
// that are done in the individual Request.
previous.begin();
}
return target;
}
requestManager.clear(target);
target.setRequest(request);
requestManager.track(target, request);
return target;
}
接下來從target中,此時(shí)是一個(gè)DrawableImageViewTarget芝雪,獲取此時(shí)是否有正在進(jìn)行的Request請求减余,如果有,則進(jìn)行邏輯判斷惩系,決定是否需要開啟一個(gè)新的位岔,還是復(fù)用之前的如筛。顯然,我們這里previous肯定是不存在的抒抬。因此需要將當(dāng)前請求去執(zhí)行杨刨,這里RequestManager先是清除掉這個(gè)traget。我們看看這個(gè)clear的實(shí)現(xiàn)擦剑。
public void clear(@Nullable final Target<?> target) {
if (target == null) {
return;
}
if (Util.isOnMainThread()) {
untrackOrDelegate(target);
} else {
mainHandler.post(new Runnable() {
@Override
public void run() {
clear(target);
}
});
}
}
此時(shí)我們情景在主線程妖胀,那就是直接調(diào)用到untrackOrDelegate方法。
private void untrackOrDelegate(@NonNull Target<?> target) {
boolean isOwnedByUs = untrack(target);
....
if (!isOwnedByUs && !glide.removeFromManagers(target) && target.getRequest() != null) {
Request request = target.getRequest();
target.setRequest(null);
request.clear();
}
}
它的實(shí)現(xiàn)也很簡單抓于,其實(shí)就是判斷當(dāng)前target上面是否有請求做粤,進(jìn)行一些邏輯判斷是否需要取消。這個(gè)細(xì)節(jié)我們暫且忽略捉撮。只需明白clear大致是處理了這些邏輯怕品。清除工作完成之后,接下來就是將當(dāng)前的request請求設(shè)置到這個(gè)target對象之中巾遭。我們簡單看下這個(gè)過程肉康,相對比較簡單。
@Override
public void setRequest(@Nullable Request request) {
setTag(request);
}
private void setTag(@Nullable Object tag) {
if (tagId == null) {
isTagUsedAtLeastOnce = true;
view.setTag(tag);
} else {
view.setTag(tagId, tag);
}
}
其實(shí)就是將Request和View做了一個(gè)綁定的關(guān)系灼舍,保存在View的tag之中吼和。這步設(shè)置完成之后,就進(jìn)入到了最后一步骑素。track當(dāng)前請求炫乓。
16.RequestManager#track
void track(@NonNull Target<?> target, @NonNull Request request) {
targetTracker.track(target);
requestTracker.runRequest(request);
}
TargetTracker和RequestTracker分別是對target和request做了一個(gè)管理,TargetTracker類中更加簡單献丑,有點(diǎn)類似一個(gè)擴(kuò)展的List結(jié)構(gòu)末捣,也就是保存了由當(dāng)前RequestManager在處理的所有Target的集合,而RequestTracker則是所有Request的集合创橄。我們要著重分析下LifecycleListener和LifeCircle的用處箩做。可以看到RequestManager妥畏、TargetTracker以及Target均實(shí)現(xiàn)了
LifecycleListener接口邦邦,RequestTracker雖然沒有直接實(shí)現(xiàn)LifecycleListener,但內(nèi)部也是有幾個(gè)相應(yīng)的生命周期感知的方法醉蚁,RequestManager的構(gòu)造方法實(shí)現(xiàn)如下燃辖。
RequestManager(
Glide glide,
Lifecycle lifecycle,
RequestManagerTreeNode treeNode,
RequestTracker requestTracker,
ConnectivityMonitorFactory factory,
Context context) {
this.glide = glide;
this.lifecycle = lifecycle;
this.treeNode = treeNode;
this.requestTracker = requestTracker;
this.context = context;
connectivityMonitor =
factory.build(
context.getApplicationContext(),
new RequestManagerConnectivityListener(requestTracker));
// If we're the application level request manager, we may be created on a background thread.
// In that case we cannot risk synchronously pausing or resuming requests, so we hack around the
// issue by delaying adding ourselves as a lifecycle listener by posting to the main thread.
// This should be entirely safe.
if (Util.isOnBackgroundThread()) {
mainHandler.post(addSelfToLifecycle);
} else {
lifecycle.addListener(this);
}
lifecycle.addListener(connectivityMonitor);
setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());
glide.registerRequestManager(this);
}
可以看到,真正和宿主Acytivity綁定的正是這個(gè)RequestManager對象网棍,所有生命周期變動(dòng)也都是先通過RequestManager來進(jìn)行分發(fā)郭赐。我們可以簡單看RequestManager中,onStart/onStop/onDestroy均是做了一些下發(fā)生命周期的變化确沸,通知到相關(guān)的類捌锭,比如到RequestTracker和TargetTracker,由RequestTracker再操作各個(gè)Request罗捎,而由TargetTracker再去管理各個(gè)Target观谦。這樣各個(gè)部分就可以根據(jù)LifiCircle進(jìn)行相關(guān)的操作,如RequestTracker中進(jìn)行取消和啟動(dòng)Request等桨菜。至此豁状,大致就明白了LifecycleListener和LifeCircle的作用,其實(shí)也沒有什么神秘倒得。無非就是找到注冊的地方泻红,和接收的對象。接下來霞掺,我們分析最后runRequest的實(shí)現(xiàn)谊路。
17.RequestTracker#runRequest
public void runRequest(@NonNull Request request) {
requests.add(request);
if (!isPaused) {
request.begin();
} else {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Paused, delaying request");
}
pendingRequests.add(request);
}
}
這個(gè)方法中,分為兩種情況菩彬,isPaused變量標(biāo)識(shí)界面是否處于onStop狀態(tài)缠劝,如果此時(shí)還可見,則直接調(diào)用request#begin方法執(zhí)行骗灶,否則則是加入到pendingRequests中惨恭,這里pendingRequests的作用僅僅是為了保證Request不被Gc,因?yàn)閞equests是一個(gè)WeakHashMap耙旦,如果不使用pendingRequests強(qiáng)引用緩存脱羡,那么這個(gè)請求就有可能被回收掉,這里是做了這樣一個(gè)處理免都,就能保證這些request不被系統(tǒng)回收掉锉罐,同時(shí)在requests也一定存在。下面我們繼續(xù)分析begin這個(gè)方法琴昆。
@Override
public void begin() {
assertNotCallingCallbacks();
stateVerifier.throwIfRecycled();
startTime = LogTime.getLogTime();
if (model == null) {
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
width = overrideWidth;
height = overrideHeight;
}
// Only log at more verbose log levels if the user has set a fallback drawable, because
// fallback Drawables indicate the user expects null models occasionally.
int logLevel = getFallbackDrawable() == null ? Log.WARN : Log.DEBUG;
onLoadFailed(new GlideException("Received null model"), logLevel);
return;
}
if (status == Status.RUNNING) {
throw new IllegalArgumentException("Cannot restart a running request");
}
// If we're restarted after we're complete (usually via something like a notifyDataSetChanged
// that starts an identical request into the same Target or View), we can simply use the
// resource and size we retrieved the last time around and skip obtaining a new size, starting a
// new load etc. This does mean that users who want to restart a load because they expect that
// the view size has changed will need to explicitly clear the View or Target before starting
// the new load.
if (status == Status.COMPLETE) {
onResourceReady(resource, DataSource.MEMORY_CACHE);
return;
}
// Restarts for requests that are neither complete nor running can be treated as new requests
// and can run again from the beginning.
status = Status.WAITING_FOR_SIZE;
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
onSizeReady(overrideWidth, overrideHeight);
} else {
target.getSize(this);
}
if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)
&& canNotifyStatusChanged()) {
target.onLoadStarted(getPlaceholderDrawable());
}
if (IS_VERBOSE_LOGGABLE) {
logV("finished run method in " + LogTime.getElapsedMillis(startTime));
}
}
這個(gè)方法中氓鄙,先是對model進(jìn)行判斷,這個(gè)model此時(shí)就是我們傳的那個(gè)url业舍,如果為空抖拦,則直接load失敗,然后是一些狀態(tài)的檢查和一些回調(diào)方法等舷暮,接下來判斷size态罪,如果是有效的,則觸發(fā)去真正的請求下面,否則則是設(shè)置一個(gè)回調(diào)复颈,等待view布局有size之后,再來觸發(fā)請求沥割,真正的請求其實(shí)就在onSizeReady中被得到執(zhí)行耗啦。
18.SingleRequest#onSizeReady
@Override
public void onSizeReady(int width, int height) {
stateVerifier.throwIfRecycled();
if (IS_VERBOSE_LOGGABLE) {
logV("Got onSizeReady in " + LogTime.getElapsedMillis(startTime));
}
if (status != Status.WAITING_FOR_SIZE) {
return;
}
status = Status.RUNNING;
float sizeMultiplier = requestOptions.getSizeMultiplier();
this.width = maybeApplySizeMultiplier(width, sizeMultiplier);
this.height = maybeApplySizeMultiplier(height, sizeMultiplier);
if (IS_VERBOSE_LOGGABLE) {
logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime));
}
loadStatus = engine.load(
glideContext,
model,
requestOptions.getSignature(),
this.width,
this.height,
requestOptions.getResourceClass(),
transcodeClass,
priority,
requestOptions.getDiskCacheStrategy(),
requestOptions.getTransformations(),
requestOptions.isTransformationRequired(),
requestOptions.isScaleOnlyOrNoTransform(),
requestOptions.getOptions(),
requestOptions.isMemoryCacheable(),
requestOptions.getUseUnlimitedSourceGeneratorsPool(),
requestOptions.getUseAnimationPool(),
requestOptions.getOnlyRetrieveFromCache(),
this);
// This is a hack that's only useful for testing right now where loads complete synchronously
// even though under any executor running on any thread but the main thread, the load would
// have completed asynchronously.
if (status != Status.RUNNING) {
loadStatus = null;
}
if (IS_VERBOSE_LOGGABLE) {
logV("finished onSizeReady in " + LogTime.getElapsedMillis(startTime));
}
}
這個(gè)方法中凿菩,首先檢查狀態(tài)是不是在等待size,如果不是帜讲,則表明size已經(jīng)有了衅谷,下面則是更新狀態(tài)到Status.RUNNING,進(jìn)而去調(diào)用Engine根據(jù)參數(shù)似将,這里面包含了所有的參數(shù)信息获黔,緩存,圖片顯示等等在验,然后去開始真正請求玷氏,網(wǎng)絡(luò)、內(nèi)存腋舌、磁盤緩存等等盏触。這塊的東西很復(fù)雜,暫且放一放侦厚,這塊設(shè)計(jì)到一個(gè)結(jié)果的回調(diào)耻陕。
/**
* A callback that listens for when a resource load completes successfully or fails due to an
* exception.
*/
public interface ResourceCallback {
/**
* Called when a resource is successfully loaded.
*
* @param resource The loaded resource.
*/
void onResourceReady(Resource<?> resource, DataSource dataSource);
/**
* Called when a resource fails to load successfully.
*
* @param e a non-null {@link GlideException}.
*/
void onLoadFailed(GlideException e);
}
實(shí)現(xiàn)是在SignleRequest中,具體代碼大家可自行分析刨沦,顯然诗宣,必須要做的一件事情是告訴Target此時(shí)的加載結(jié)果,再由Target去通知View做如何的展示想诅,實(shí)際上召庞,也是這樣子實(shí)現(xiàn)的。具體細(xì)節(jié)這里不展開了来破。最后回到第17步篮灼,還有一個(gè)比較簡單的方法Target#onLoadStarted。
19.Target#onLoadStarted
@Override
public void onLoadStarted(@Nullable Drawable placeholder) {
super.onLoadStarted(placeholder);
setResourceInternal(null);
setDrawable(placeholder);
}
這個(gè)方法的實(shí)現(xiàn)很簡單徘禁,就是為view提前設(shè)置一些狀態(tài)诅诱,比如placeholder信息等等,然后等待Engine后續(xù)的加載完成送朱。
至此娘荡,這一塊簡單的流程就已經(jīng)介紹結(jié)束,基本的加載流程和LifiCircle的東西想必有了一個(gè)初步的認(rèn)識(shí)驶沼,從文章分析來看炮沐,最復(fù)雜的部分可能就是Engine根據(jù)參數(shù)來具體加載的過程了,后續(xù)繼續(xù)分析回怜。在此大年,ImageView上面就已經(jīng)能夠正常的顯示出圖片了。