下面來(lái)看在Glide中最簡(jiǎn)單的圖片加載代碼
Glide.with(this)
.load("https://p.upyun.com/docs/cloud/demo.jpg")
.into(imageView);
這應(yīng)該是相對(duì)比較簡(jiǎn)單的加載圖片的代碼了求豫,一步步來(lái)右蒲,看代碼其實(shí)很講究耐心幢妄,有時(shí)候會(huì)遇到很多層次的調(diào)用鏈拟糕,這個(gè)時(shí)候其實(shí)很有必要自己畫(huà)一些圖判呕,很能幫助理清一些思路倦踢。下面來(lái)看這段比較看似比較簡(jiǎn)單的代碼,其實(shí)在Glide源碼中侠草,運(yùn)用到了大量的類的設(shè)計(jì)辱挥,后面涉及的我會(huì)慢慢介紹到。
首先簡(jiǎn)單介紹下這個(gè)Glide類边涕,它相當(dāng)于是整個(gè)框架的調(diào)用入口晤碘,有一點(diǎn)像外觀模式,一般很多第三方sdk都會(huì)用到這種模式功蜓,提供一個(gè)高層接口园爷,減少用戶的使用成本,對(duì)于我們第一個(gè)with方法式撼,這個(gè)其實(shí)就是一個(gè)工廠方法童社,雖然有許多重載的形式,其實(shí)都是要?jiǎng)?chuàng)建一個(gè)RequestManager對(duì)象著隆。下面我們來(lái)看這個(gè)
這個(gè)with方法扰楼,如下:
icon_glide_with.png
Glide#with方法有六個(gè)重載的形式,但是第一部分都是調(diào)用Glide#getRetriever獲取一個(gè)RequestManagerRetriever對(duì)象美浦,進(jìn)而調(diào)用RequestManagerRetriever#get方法最終創(chuàng)建一個(gè)RequestManager對(duì)象弦赖。下面一個(gè)個(gè)來(lái)進(jìn)行分析。
1.Glide#with
@NonNull
public static RequestManager with(@NonNull FragmentActivity activity) {
return getRetriever(activity).get(activity);
}
還有其他的重載形式浦辨,其實(shí)第一部分都是一樣蹬竖,都是獲取他們(Actvity/View/Fragment等)的上下文,然后通過(guò)getRetriever方法去獲取一個(gè)RequestManagerRetriever對(duì)象流酬。進(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的單例對(duì)象芽腾,初始化Glide對(duì)象時(shí)劈榨,做了很多復(fù)雜的配置信息,包括緩存策略等等晦嵌,這里我們暫時(shí)跳過(guò)同辣,后續(xù)講到這些配置信息再詳細(xì)分析,有時(shí)候惭载,看代碼要忽略其他的細(xì)節(jié)旱函,沿著一條主線走,站在宏觀的視角描滔,針對(duì)具體問(wèn)題再行微觀分析棒妨,往往會(huì)比較清晰。這里獲取到一個(gè)Glide實(shí)例之后,回到第2步券腔,接下來(lái)回到Glide#getRetriever伏穆,然后是調(diào)用了Glide#getRequestManagerRetriever繼續(xù)請(qǐng)求。
4.Glide#getRequestManagerRetriever
@NonNull
public RequestManagerRetriever getRequestManagerRetriever() {
return requestManagerRetriever;
}
這個(gè)方法很簡(jiǎn)單纷纫,就是返回一個(gè)RequestManagerRetriever對(duì)象枕扫,那么它是在什么時(shí)候初始化的呢,通過(guò)代碼分析辱魁,在Glide初始化時(shí)候烟瞧,會(huì)初始化這個(gè)requestManagerRetriever對(duì)象,我們暫且略過(guò)它染簇。有了這個(gè)requestManagerRetriever對(duì)象后参滴,回到第1步,接下來(lái)會(huì)調(diào)用RequestManagerRetriever#get方法锻弓,與Glide#with對(duì)應(yīng)砾赔,它也有6個(gè)重載的形式,均是返回一個(gè)RequestManager青灼。
5.RequestManagerRetriever#get
icon_request_manager_retriever_get.png
雖然是有這么多重載形式过蹂,但都是一個(gè)平行的關(guān)系,為了理解原理聚至,去繁為簡(jiǎ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ù)再來(lái)分析一些分支的情況∠就伲可以看到促脉,在ui線程中,首先是獲取了support下面的FragmentManager對(duì)象策州,然后繼續(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è)道理孽糖,我們可以假定某一種情況枯冈,便于代碼的主線分析毅贮。接下來(lái)是構(gòu)建了一個(gè)SupportRequestManagerFragment對(duì)象,它就是一個(gè)Fragment對(duì)象尘奏,其實(shí)沒(méi)有什么神秘滩褥,它里面綁定了一些Lifecycle的方法,后續(xù)我們會(huì)看到罪既。這里其實(shí)用了一個(gè)技巧铸题,因?yàn)槲覀兛吹剑櫼粋€(gè)Activity的生命周期琢感,同時(shí)又要能夠達(dá)到通用性丢间,顯然在用戶的業(yè)務(wù)Activity中是不太可能能插入生命周期的鉤子方法,那么驹针,作為一個(gè)框架層面的烘挫,顯然要必備一些通用性才行,這里Glide是通過(guò)手動(dòng)添加一個(gè)隱藏的SupportRequestManagerFragment對(duì)象柬甥,通過(guò)監(jiān)聽(tīng)它的生命周期變化而達(dá)到監(jiān)聽(tīng)到宿主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;
}
這里沒(méi)有什么比較難的,唯獨(dú)就是有一個(gè)小技巧臂外,為什么需要這個(gè)pendingSupportRequestManagerFragments對(duì)象窟扑,它其實(shí)是為了避免重復(fù)創(chuàng)建SupportRequestManagerFragment對(duì)象,這里有兩個(gè)if檢查漏健,初學(xué)者可能會(huì)有點(diǎn)奇怪嚎货,這是因?yàn)镕ragmentManager提交這個(gè)方法是一個(gè)消息機(jī)制觸發(fā)的形式,并不會(huì)立即的執(zhí)行蔫浆,如果此時(shí)多次調(diào)用而沒(méi)有pendingSupportRequestManagerFragments的保證殖属,是會(huì)多次建立對(duì)象的。顯然添加到fm中后瓦盛,就不再需要pendingSupportRequestManagerFragments洗显,所以在下一個(gè)消息到達(dá)時(shí)候,ID_REMOVE_SUPPORT_FRAGMENT_MANAGER中及時(shí)的被移除原环。然后這里我們看到isParentVisible這個(gè)變量墙懂,其實(shí)是觸發(fā)Lifecycle的一些回調(diào)。有了這個(gè)Fragment之后扮念,我們繼續(xù)回到第6步的邏輯损搬。這里就開(kāi)始了RequestManager的構(gòu)造,然后再設(shè)置到SupportRequestManagerFragment的成員變量requestManager中。下面我們繼續(xù)分析這個(gè)RequestManager的構(gòu)造過(guò)程巧勤。這里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對(duì)象颅悉,至此創(chuàng)建RequestManager的任務(wù)就已經(jīng)完成沽瞭,Glide#with方法執(zhí)行完成,這里我們可以看到剩瓶,RequestManager對(duì)于同一個(gè)上下文來(lái)說(shuō)是唯一的驹溃。下面我們繼續(xù)分析GlideRequests的load方法。
9.GlideRequests#load
@Override
@NonNull
@CheckResult
public GlideRequest<Drawable> load(@Nullable String string) {
return (GlideRequest<Drawable>) super.load(string);
}
這個(gè)很簡(jiǎn)單延曙,直接是調(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對(duì)于請(qǐng)求的各種鏈?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è)置顿涣。接下來(lái)進(jìn)入到步驟10,通過(guò)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è)方法也很簡(jiǎn)單,只是設(shè)置了model這個(gè)屬性的值舔痪,至此寓调,load(url)方法全部結(jié)束。接下來(lái)分析最后一個(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,主要涉及到圖片的展示滋捶,這里我們也暫且跳過(guò)痛悯,它有一個(gè)默認(rèn)值。transcodeClass就是我們上面?zhèn)魅氲腄rawable.class重窟,接下來(lái)分析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è)對(duì)象之后,我們繼續(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;
}
前面的檢查邏輯跳過(guò)搀突,這里我們的targetListener是null,target是一個(gè)DrawableImageViewTarget對(duì)象熊泵,然后是通過(guò)buildRequest方法仰迁,創(chuàng)建了一個(gè)Request對(duì)象⊥绶郑看名字可以知道徐许,這個(gè)才是真正的請(qǐng)求,只有到into此時(shí)怯邪,才會(huì)真正的去請(qǐng)求绊寻,我們先分析這個(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;
}
這里我們并沒(méi)有設(shè)置和泌,直接跳過(guò)村缸,所以只用管mainRequest這個(gè)構(gòu)建過(guò)程,在這里武氓,我們可以看到梯皿,Glide是支持簡(jiǎn)單的嵌套R(shí)equest邏輯的,此時(shí)我們暫且跳過(guò)县恕。然后是進(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)也比較長(zhǎng),這里根據(jù)我們的邏輯忠烛,并沒(méi)有設(shè)置thumbnailBuilder和thumbSizeMultiplier属提,其實(shí)要關(guān)注的就是最后一個(gè)else邏輯,這樣分析其實(shí)能讓我不受分支的影響美尸,更容易把握整體流程冤议,呆需要深入研究thumbnai這塊時(shí)候,可以繼續(xù)去挖掘师坎。下面我們繼續(xù)看沒(méi)有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è)方法的名字胯陋,是不是覺(jué)得很熟悉蕊温,對(duì)袱箱,我們的Handler里面就有類似的方法,這里Glide用到了享元的一種設(shè)計(jì)模式寿弱,出于對(duì)內(nèi)存的節(jié)省犯眠。接下來(lái)繼續(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;
}
可以看到症革,先是從對(duì)象池里面去取筐咧,有則共享,減少new對(duì)象的成本噪矛。然后調(diào)用init方法量蕊,進(jìn)行一些參數(shù)設(shè)置。最后我們看到艇挨,一個(gè)request對(duì)象的創(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;
}
接下來(lái)從target中脉漏,此時(shí)是一個(gè)DrawableImageViewTarget苞冯,獲取此時(shí)是否有正在進(jìn)行的Request請(qǐng)求,如果有侧巨,則進(jìn)行邏輯判斷舅锄,決定是否需要開(kāi)啟一個(gè)新的,還是復(fù)用之前的司忱。顯然皇忿,我們這里previous肯定是不存在的。因此需要將當(dāng)前請(qǐ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)也很簡(jiǎn)單,其實(shí)就是判斷當(dāng)前target上面是否有請(qǐng)求锻离,進(jìn)行一些邏輯判斷是否需要取消铺峭。這個(gè)細(xì)節(jié)我們暫且忽略墓怀。只需明白clear大致是處理了這些邏輯汽纠。清除工作完成之后,接下來(lái)就是將當(dāng)前的request請(qǐng)求設(shè)置到這個(gè)target對(duì)象之中傀履。我們簡(jiǎn)單看下這個(gè)過(guò)程虱朵,相對(duì)比較簡(jiǎn)單莉炉。
@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)前請(qǐng)求服协。
16.RequestManager#track
void track(@NonNull Target<?> target, @NonNull Request request) {
targetTracker.track(target);
requestTracker.runRequest(request);
}
TargetTracker和RequestTracker分別是對(duì)target和request做了一個(gè)管理绍昂,TargetTracker類中更加簡(jiǎn)單,有點(diǎn)類似一個(gè)擴(kuò)展的List結(jié)構(gòu)偿荷,也就是保存了由當(dāng)前RequestManager在處理的所有Target的集合窘游,而RequestTracker則是所有Request的集合。我們要著重分析下LifecycleListener和LifeCircle的用處跳纳∪淌危可以看到RequestManager、TargetTracker以及Target均實(shí)現(xiàn)了
LifecycleListener接口寺庄,RequestTracker雖然沒(méi)有直接實(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對(duì)象,所有生命周期變動(dòng)也都是先通過(guò)RequestManager來(lái)進(jìn)行分發(fā)逛拱。我們可以簡(jiǎn)單看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í)也沒(méi)有什么神秘。無(wú)非就是找到注冊(cè)的地方筹麸,和接收的對(duì)象活合。接下來(lái),我們分析最后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í)還可見(jiàn)告嘲,則直接調(diào)用request#begin方法執(zhí)行错维,否則則是加入到pendingRequests中,這里pendingRequests的作用僅僅是為了保證Request不被Gc橄唬,因?yàn)閞equests是一個(gè)WeakHashMap赋焕,如果不使用pendingRequests強(qiáng)引用緩存,那么這個(gè)請(qǐng)求就有可能被回收掉仰楚,這里是做了這樣一個(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è)方法中,先是對(duì)model進(jìn)行判斷捎泻,這個(gè)model此時(shí)就是我們傳的那個(gè)url飒炎,如果為空,則直接load失敗笆豁,然后是一些狀態(tài)的檢查和一些回調(diào)方法等郎汪,接下來(lái)判斷size,如果是有效的闯狱,則觸發(fā)去真正的請(qǐng)求煞赢,否則則是設(shè)置一個(gè)回調(diào),等待view布局有size之后哄孤,再來(lái)觸發(fā)請(qǐng)求照筑,真正的請(qǐng)求其實(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īng)顟B(tài)到Status.RUNNING跑芳,進(jìn)而去調(diào)用Engine根據(jù)參數(shù),這里面包含了所有的參數(shù)信息,緩存,圖片顯示等等支鸡,然后去開(kāi)始真正請(qǐng)求,網(wǎng)絡(luò)趁窃、內(nèi)存牧挣、磁盤(pán)緩存等等。這塊的東西很復(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é)這里不展開(kāi)了怕犁。最后回到第17步,還有一個(gè)比較簡(jiǎn)單的方法Target#onLoadStarted己莺。
19.Target#onLoadStarted
@Override
public void onLoadStarted(@Nullable Drawable placeholder) {
super.onLoadStarted(placeholder);
setResourceInternal(null);
setDrawable(placeholder);
}
這個(gè)方法的實(shí)現(xiàn)很簡(jiǎn)單奏甫,就是為view提前設(shè)置一些狀態(tài),比如placeholder信息等等凌受,然后等待Engine后續(xù)的加載完成阵子。
至此,這一塊簡(jiǎn)單的流程就已經(jīng)介紹結(jié)束胜蛉,基本的加載流程和LifiCircle的東西想必有了一個(gè)初步的認(rèn)識(shí)挠进,從文章分析來(lái)看,最復(fù)雜的部分可能就是Engine根據(jù)參數(shù)來(lái)具體加載的過(guò)程了誊册,后續(xù)繼續(xù)分析领突。在此,ImageView上面就已經(jīng)能夠正常的顯示出圖片了案怯。