Glide 作為Google 出品的圖片加載庫(kù),在開(kāi)發(fā)的過(guò)程中對(duì)我們的幫助是非常大的,網(wǎng)上也有很多關(guān)于他的文章,說(shuō)他怎么怎么好,但是他就是再好我們?nèi)绻恢浪脑硪部隙ㄊ怯洸蛔〉?而且關(guān)于圖片的操作在面試過(guò)程中是必然要問(wèn)到的,如果你只是知道怎么用的話肯定是不能打動(dòng)面試官的,如果你能從源碼方面說(shuō)一下,肯定會(huì)讓對(duì)方眼前一亮的,廢話不多說(shuō),我們由簡(jiǎn)入繁的開(kāi)始分析一下一張圖片在Glide都經(jīng)歷了什么,
想要弄清楚整個(gè)圖片的加載過(guò)程,如果上來(lái)就看源碼的話大家肯定會(huì)非常懵,還是需要先弄清楚每個(gè)類在Glide中扮演的角色,這樣便于大家的理解,即使部分代碼不懂,但是知道了他是干什么也能猜測(cè)一個(gè)大概,同時(shí)也方便我們?cè)诜治鲞^(guò)程中查看
Glide 中重要的角色
1.Glide
Glide作為圖片加載的入口, 當(dāng)中保存著非常重要的數(shù)據(jù),在整個(gè)請(qǐng)求中非常重要,創(chuàng)建方式: DCL 單例
2.RequestManagerRetriever
RequestManagerRetriever 作為RequestManager 管理者,調(diào)度著當(dāng)前請(qǐng)求應(yīng)該分配給哪個(gè)RequestManager,創(chuàng)建方式:new 伴隨著Glide同時(shí)創(chuàng)建
3.RequestManager
RequestManager 作為請(qǐng)求的承載者,中控器, 在當(dāng)中扮演著非常重要的角色, 創(chuàng)建方式: new 不同的是并不是每次請(qǐng)求都創(chuàng)建,而是在同一個(gè)activity中只創(chuàng)建一個(gè),部分情況可能將這個(gè)請(qǐng)求分配給ApplicationContext,
4.Request
這個(gè)一看就知道是請(qǐng)求, 重要的請(qǐng)求類 SingleRequest ThumbnailRequestCoordinator (包含2個(gè)請(qǐng)求,判斷也非常簡(jiǎn)單,后面我們會(huì)單獨(dú)做分析)
創(chuàng)建方式 : 緩存池 ,防止大量創(chuàng)建對(duì)象浪費(fèi)時(shí)間,頻繁銷毀對(duì)象導(dǎo)致內(nèi)存抖動(dòng),同樣的方式 Handler.obtainMessage 也是如此
5.RequestBuilder
用來(lái)構(gòu)建請(qǐng)求時(shí)的參數(shù),通常會(huì)繼承開(kāi)發(fā)者在全局的配置,如果有改動(dòng)會(huì)替換響應(yīng)的改動(dòng).創(chuàng)建方式:new 無(wú)特殊方式,但是需要注意的是RequestBuilder的創(chuàng)建開(kāi)始的方法是 as(classType.class) ,即使是Glide.with(context).load(resId),看似我們是調(diào)用的load 的方法創(chuàng)建了這個(gè)RequestBuilder,實(shí)際操作還是調(diào)用的as 方法
@NonNull
@CheckResult
@Override
public RequestBuilder<Drawable> load(@RawRes @DrawableRes @Nullable Integer resourceId) {
return asDrawable().load(resourceId);
}
@NonNull
@CheckResult
public RequestBuilder<Drawable> asDrawable() {
return as(Drawable.class);
}
6.Target
Target 是作為回調(diào)參與進(jìn)來(lái)的,他不僅僅參與下載后作為最后資源出口,還會(huì)參與下載過(guò)程中獲取圖片的載體的寬高等等,
7.Engine
Engine 的做用是發(fā)起請(qǐng)求,實(shí)際的請(qǐng)求過(guò)程就是在他的內(nèi)部實(shí)現(xiàn)的,創(chuàng)建方式:new 伴隨著Glide 創(chuàng)建的
至此整個(gè)加載過(guò)程中涉及到的角色我們就分析完了,下面我們進(jìn)入正題,開(kāi)始分析一下最簡(jiǎn)單的請(qǐng)求
Glide.with(context).load(resId).into(imageView);
Glide.with(context)
@NonNull
public static RequestManager with(@NonNull Context context) {
return getRetriever(context).get(context);
}
先是getRetriever ,通過(guò)getRetriever 來(lái)獲取RequestManager
Glide.getRetriever(@Nullable Context context)
@NonNull
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
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();
}
顯示check一下context ,然后通過(guò)Glide 獲取RequestManagerRetriever
Glide.get(@NonNull Context context)
private static volatile Glide glide;
@NonNull
public static Glide get(@NonNull Context context) {
if (glide == null) {
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context);///初始化配置信息
}
}
}
return 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;
}
private static void initializeGlide(@NonNull Context context) {
initializeGlide(context, new GlideBuilder());
}
GlideBuilder.build(Context context)
if (engine == null) {
engine =
new Engine(
memoryCache,
diskCacheFactory,
diskCacheExecutor,
sourceExecutor,
GlideExecutor.newUnlimitedSourceExecutor(),
GlideExecutor.newAnimationExecutor(),
isActiveResourceRetentionAllowed);
}
if (defaultRequestListeners == null) {
defaultRequestListeners = Collections.emptyList();
} else {
defaultRequestListeners = Collections.unmodifiableList(defaultRequestListeners);
}
RequestManagerRetriever requestManagerRetriever =
new RequestManagerRetriever(requestManagerFactory);
這里的GlideBuilder 初始化了非常多的配置信息,這里我貼了兩個(gè)比較重要的Engine 和RequestManagerRetriever ,可以看到這些都是伴隨著Glide 同時(shí)初始化的,也就是整個(gè)工程就只有一個(gè),
@NonNull
public static RequestManager with(@NonNull Context context) {
return getRetriever(context).get(context);
}
現(xiàn)在再看上面的方法大家應(yīng)該已經(jīng)知道了getRetriever()方法的大概,如果是第一次調(diào)用的話會(huì)使用DCL單利模式創(chuàng)建 Glide ,伴隨著Glide 的創(chuàng)建同時(shí)會(huì)初始化一些配置信息比如 : RequestManagerRetriever Engine 等
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)) {
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);
}
可以看到如果不是在主線程就使用ApplicationManage,這里我看一下FragmentActivity的分支,他的處理方法比較特殊,具體怎么特殊我們進(jìn)去看一下,
RequestManagerRetriever.get(@NonNull FragmentActivity activity)
@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));
}
}
這里沒(méi)啥東西,繼續(xù)往里面走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;
}
在這里看到了創(chuàng)建RequestManager 的方法,同時(shí)把自己創(chuàng)建的Fragemnt的 Lifecycle傳遞給了 RequestManager , 供RequestManager 來(lái)監(jiān)聽(tīng)宿主Activity的狀態(tài),來(lái)停止請(qǐng)求,這里我們粘貼一些方法
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);
.....
}
lifecycle.addListener(this); 方法將自身作為參數(shù),就可以監(jiān)聽(tīng)到狀態(tài)了,
我們看看RequestManager在生命周期方法中他都干了什么
@Override
public synchronized void onStart() {
resumeRequests();
targetTracker.onStart();
}
/**
* Lifecycle callback that unregisters for connectivity events (if the
* android.permission.ACCESS_NETWORK_STATE permission is present) and pauses in progress loads.
*/
@Override
public synchronized void onStop() {
pauseRequests();
targetTracker.onStop();
}
/**
* Lifecycle callback that cancels all in progress requests and clears and recycles resources for
* all completed requests.
*/
@Override
public synchronized void onDestroy() {
targetTracker.onDestroy();
for (Target<?> target : targetTracker.getAll()) {
clear(target);
}
targetTracker.clear();
requestTracker.clearRequests();
lifecycle.removeListener(this);
lifecycle.removeListener(connectivityMonitor);
mainHandler.removeCallbacks(addSelfToLifecycle);
glide.unregisterRequestManager(this);
}
在onDestroy 中回收信息,onStart 開(kāi)始請(qǐng)求,onStop 暫停請(qǐng)求,看到這里我就知道了Glide 是如何與生命周期作為綁定的,
看到這里我們發(fā)現(xiàn)他將RequestManager 放到了SupportRequestManagerFragment 里面,過(guò)去看了一下SupportRequestManagerFragment ,他就是一個(gè)普通的Fragment,沒(méi)什么特別的,我們繼續(xù)看看他是如何得到這個(gè)Fragment的,繼續(xù)看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;
}
看到這里我們恍然大悟,他在FragmentActivity中綁定了一個(gè)Fragment,通過(guò)這個(gè)Fragment來(lái)共享改Activity 的RequestManager ,同時(shí)可以感知這個(gè)Activity 的 聲明周期,
看到了這里已經(jīng)將Glide.with(context) 看完了,繼續(xù)看load(String url)
RequestManager.load(@Nullable String string)
@NonNull
@CheckResult
@Override
public RequestBuilder<Drawable> load(@Nullable String string) {
return asDrawable().load(string);
}
@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);
}
可以看到即使我們調(diào)用RequestManager.load()方法,他最終還是調(diào)用了as 方法來(lái)new RequestBuilder,設(shè)置其他參數(shù)這里就不分析了,繼續(xù)看RequestBuilder.into(@NonNull ImageView view)
RequestBuilder.into(@NonNull ImageView view)
@NonNull
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
Util.assertMainThread();
Preconditions.checkNotNull(view);
BaseRequestOptions<?> requestOptions = this;
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,
Executors.mainThreadExecutor());
}
這里針對(duì)ScanType 做了一些配置參數(shù),但是我們使用的是最簡(jiǎn)單的方法,所以這些參數(shù)都沒(méi)有,直接看下面的into 方法,
可以看到into方法的第一個(gè)參數(shù)是通過(guò)glideContext ,view ,transcodeClass就是我們使用 load 的時(shí)候所調(diào)用的as 方法中Drawable,
@NonNull
public <X> ViewTarget<ImageView, X> buildImageViewTarget(
@NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {
return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
}
這里調(diào)用了ImageViewTargetFactory 的 buildTarget方法,沒(méi)有什么特別的,
ImageViewTargetFactory.buildTarget(@NonNull ImageView view,@NonNull Class<Z> clazz)
public class ImageViewTargetFactory {
@NonNull
@SuppressWarnings("unchecked")
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)");
}
}
}
可以看到如果是Drawable的話返回的就是DrawableImageViewTarget ,回去繼續(xù)看into 方法
RequestBuilder <Y extends Target<TranscodeType>> Y into( @NonNull Y target,@Nullable RequestListener<TranscodeType> targetListener,BaseRequestOptions<?> options, Executor callbackExecutor)
private <Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener,
BaseRequestOptions<?> options,
Executor callbackExecutor) {
Preconditions.checkNotNull(target);
if (!isModelSet) {
throw new IllegalArgumentException("You must call #load() before calling #into()");
}
Request request = buildRequest(target, targetListener, options, callbackExecutor);
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;
}
看到這里我們終于將請(qǐng)求時(shí)候的參數(shù)都已經(jīng)創(chuàng)建完畢了,已經(jīng)開(kāi)始創(chuàng)建Request 了,這里看到他首先判斷了 isModelSet 這個(gè)變量,isModelSet這個(gè)變量就是在調(diào)用load 方法的時(shí)候設(shè)置true 的,所以看他拋出異常的文言,在into 方法之前必須先調(diào)用load 方法,接下來(lái)構(gòu)建了一個(gè)Request
RequestBuilder buildRequest
private Request buildRequest(
Target<TranscodeType> target,
@Nullable RequestListener<TranscodeType> targetListener,
BaseRequestOptions<?> requestOptions,
Executor callbackExecutor) {
return buildRequestRecursive(
target,
targetListener,
/*parentCoordinator=*/ null,
transitionOptions,
requestOptions.getPriority(),
requestOptions.getOverrideWidth(),
requestOptions.getOverrideHeight(),
requestOptions,
callbackExecutor);
}
這里獲取了RequestBuilder 的OverrideWidth和OverrideHeight,但是我們沒(méi)有設(shè)置,這里應(yīng)該是默認(rèn)值,''
RequestBuilder buildRequestRecursive
private Request buildRequestRecursive(
Target<TranscodeType> target,
@Nullable RequestListener<TranscodeType> targetListener,
@Nullable RequestCoordinator parentCoordinator,
TransitionOptions<?, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight,
BaseRequestOptions<?> requestOptions,
Executor callbackExecutor) {
// 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,
callbackExecutor);
if (errorRequestCoordinator == null) {
return mainRequest;
}
int errorOverrideWidth = errorBuilder.getOverrideWidth();
int errorOverrideHeight = errorBuilder.getOverrideHeight();
if (Util.isValidDimensions(overrideWidth, overrideHeight)
&& !errorBuilder.isValidOverride()) {
errorOverrideWidth = requestOptions.getOverrideWidth();
errorOverrideHeight = requestOptions.getOverrideHeight();
}
Request errorRequest =
errorBuilder.buildRequestRecursive(
target,
targetListener,
errorRequestCoordinator,
errorBuilder.transitionOptions,
errorBuilder.getPriority(),
errorOverrideWidth,
errorOverrideHeight,
errorBuilder,
callbackExecutor);
errorRequestCoordinator.setRequests(mainRequest, errorRequest);
return errorRequestCoordinator;
}
這里我們沒(méi)有設(shè)置erroe的信息, 所以返回的是buildThumbnailRequestRecursive
RequestBuilder buildThumbnailRequestRecursive
private Request buildThumbnailRequestRecursive(
Target<TranscodeType> target,
RequestListener<TranscodeType> targetListener,
@Nullable RequestCoordinator parentCoordinator,
TransitionOptions<?, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight,
BaseRequestOptions<?> requestOptions,
Executor callbackExecutor) {
if (thumbnailBuilder != null) {
// Recursive case: contains a potentially recursive thumbnail request builder.
if (isThumbnailBuilt) {
throw new IllegalStateException("You cannot use a request as both the main request and a "
+ "thumbnail, consider using clone() on the request(s) passed to thumbnail()");
}
TransitionOptions<?, ? super TranscodeType> thumbTransitionOptions =
thumbnailBuilder.transitionOptions;
// Apply our transition by default to thumbnail requests but avoid overriding custom options
// that may have been applied on the thumbnail request explicitly.
if (thumbnailBuilder.isDefaultTransitionOptionsSet) {
thumbTransitionOptions = transitionOptions;
}
Priority thumbPriority = thumbnailBuilder.isPrioritySet()
? thumbnailBuilder.getPriority() : getThumbnailPriority(priority);
int thumbOverrideWidth = thumbnailBuilder.getOverrideWidth();
int thumbOverrideHeight = thumbnailBuilder.getOverrideHeight();
if (Util.isValidDimensions(overrideWidth, overrideHeight)
&& !thumbnailBuilder.isValidOverride()) {
thumbOverrideWidth = requestOptions.getOverrideWidth();
thumbOverrideHeight = requestOptions.getOverrideHeight();
}
ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
Request fullRequest =
obtainRequest(
target,
targetListener,
requestOptions,
coordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
callbackExecutor);
isThumbnailBuilt = true;
// Recursively generate thumbnail requests.
Request thumbRequest =
thumbnailBuilder.buildRequestRecursive(
target,
targetListener,
coordinator,
thumbTransitionOptions,
thumbPriority,
thumbOverrideWidth,
thumbOverrideHeight,
thumbnailBuilder,
callbackExecutor);
isThumbnailBuilt = false;
coordinator.setRequests(fullRequest, thumbRequest);
return coordinator;
} else if (thumbSizeMultiplier != null) {
// Base case: thumbnail multiplier generates a thumbnail request, but cannot recurse.
ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
Request fullRequest =
obtainRequest(
target,
targetListener,
requestOptions,
coordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
callbackExecutor);
BaseRequestOptions<?> thumbnailOptions =
requestOptions.clone().sizeMultiplier(thumbSizeMultiplier);
Request thumbnailRequest =
obtainRequest(
target,
targetListener,
thumbnailOptions,
coordinator,
transitionOptions,
getThumbnailPriority(priority),
overrideWidth,
overrideHeight,
callbackExecutor);
coordinator.setRequests(fullRequest, thumbnailRequest);
return coordinator;
} else {
// Base case: no thumbnail.
return obtainRequest(
target,
targetListener,
requestOptions,
parentCoordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
callbackExecutor);
}
}
這里沒(méi)有設(shè)置縮略圖信息,所以調(diào)用的是obtainRequest
RequestBuilder obtainRequest
private Request obtainRequest(
Target<TranscodeType> target,
RequestListener<TranscodeType> targetListener,
BaseRequestOptions<?> requestOptions,
RequestCoordinator requestCoordinator,
TransitionOptions<?, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight,
Executor callbackExecutor) {
return SingleRequest.obtain(
context,
glideContext,
model,
transcodeClass,
requestOptions,
overrideWidth,
overrideHeight,
priority,
target,
targetListener,
requestListeners,
requestCoordinator,
glideContext.getEngine(),
transitionOptions.getTransitionFactory(),
callbackExecutor);
}
}
沒(méi)有邏輯,繼續(xù)向下看
SingleRequest obtain
public static <R> SingleRequest<R> obtain(
Context context,
GlideContext glideContext,
Object model,
Class<R> transcodeClass,
BaseRequestOptions<?> requestOptions,
int overrideWidth,
int overrideHeight,
Priority priority,
Target<R> target,
RequestListener<R> targetListener,
@Nullable List<RequestListener<R>> requestListeners,
RequestCoordinator requestCoordinator,
Engine engine,
TransitionFactory<? super R> animationFactory,
Executor callbackExecutor) {
@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,
requestListeners,
requestCoordinator,
engine,
animationFactory,
callbackExecutor);
return request;
}
看到了obtain 這個(gè)方法有沒(méi)有想起來(lái)Handler.obtainMessage 的方法,沒(méi)錯(cuò),他們的邏輯都是一樣的,使用了一個(gè)常量池來(lái)保存信息,這樣可以節(jié)省創(chuàng)建對(duì)象的時(shí)間,和頻繁銷毀對(duì)象造成的內(nèi)存抖動(dòng)
這里我們看到如果沒(méi)有設(shè)置縮略圖信息和error 信息的時(shí)候都是創(chuàng)建SingleRequest 實(shí)例,我們回頭繼續(xù)看我們沒(méi)看完的into方法,
private <Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener,
BaseRequestOptions<?> options,
Executor callbackExecutor) {
Preconditions.checkNotNull(target);
if (!isModelSet) {
throw new IllegalArgumentException("You must call #load() before calling #into()");
}
Request request = buildRequest(target, targetListener, options, callbackExecutor);
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 和request 綁定了,所以才有target.getRequest(); 和 target.setRequest(request); 這兩個(gè)方法,既然將他們綁定再來(lái)看 target.getRequest();,就知道他是什么意思,也就是獲取之前綁定的請(qǐng)求,如果前后兩個(gè)請(qǐng)求相同,則放棄新創(chuàng)建的請(qǐng)求,直接返回原來(lái)已有的請(qǐng)求,繼續(xù)看看是如何將target 和 request 綁定的
ViewTarget.setRequest(@Nullable Request request)
@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);
}
}
這個(gè)綁定就是將這個(gè)request 設(shè)置為view的tag,
接下來(lái)就應(yīng)該是請(qǐng)求了requestManager.track(target, request); 就是將這個(gè)target 放入已請(qǐng)求的隊(duì)列里面,同時(shí)開(kāi)始請(qǐng)求
RequestManager track(@NonNull Target<?> target, @NonNull Request request)
synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
targetTracker.track(target);
requestTracker.runRequest(request);
}
RequestManager runRequest
public void runRequest(@NonNull Request request) {
requests.add(request);
if (!isPaused) {
request.begin();
} else {
request.clear();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Paused, delaying request");
}
pendingRequests.add(request);
}
}
看到了根據(jù)一個(gè)標(biāo)識(shí)位來(lái)判斷是否開(kāi)啟請(qǐng)求,這個(gè)請(qǐng)求就是根據(jù)生命周期判斷的,上面我們已經(jīng)分析過(guò)了,這里的調(diào)用了request.begin() 方法,我們?cè)谏厦嬷袆?chuàng)建Request是SingleRequest,去看他的begin方法
SingleRequest begin
public synchronized void begin() {
this.assertNotCallingCallbacks();
this.stateVerifier.throwIfRecycled();
this.startTime = LogTime.getLogTime();
if (this.model == null) {
if (Util.isValidDimensions(this.overrideWidth, this.overrideHeight)) {
this.width = this.overrideWidth;
this.height = this.overrideHeight;
}
int logLevel = this.getFallbackDrawable() == null ? 5 : 3;
this.onLoadFailed(new GlideException("Received null model"), logLevel);
} else if (this.status == SingleRequest.Status.RUNNING) {
throw new IllegalArgumentException("Cannot restart a running request");
} else if (this.status == SingleRequest.Status.COMPLETE) {
this.onResourceReady(this.resource, DataSource.MEMORY_CACHE);
} else {
this.status = SingleRequest.Status.WAITING_FOR_SIZE;
if (Util.isValidDimensions(this.overrideWidth, this.overrideHeight)) {
this.onSizeReady(this.overrideWidth, this.overrideHeight);
} else {
this.target.getSize(this);
}
if ((this.status == SingleRequest.Status.RUNNING || this.status == SingleRequest.Status.WAITING_FOR_SIZE) && this.canNotifyStatusChanged()) {
this.target.onLoadStarted(this.getPlaceholderDrawable());
}
if (IS_VERBOSE_LOGGABLE) {
this.logV("finished run method in " + LogTime.getElapsedMillis(this.startTime));
}
}
}
這里還是判斷了一些狀態(tài),如果狀態(tài)是正確的,就會(huì)根據(jù)我們是否設(shè)置了overrideWidth與overrideHeight 來(lái)判斷走哪一個(gè)方法,如果我們?cè)O(shè)置了,那就是我們已經(jīng)知道了需要加載的圖片大小,如果不知道,就需要調(diào)用target 去計(jì)算寬高,
ViewTarget.getSize
void getSize(@NonNull SizeReadyCallback cb) {
int currentWidth = getTargetWidth();
int currentHeight = getTargetHeight();
if (isViewStateAndSizeValid(currentWidth, currentHeight)) {
cb.onSizeReady(currentWidth, currentHeight);
return;
}
// We want to notify callbacks in the order they were added and we only expect one or two
// callbacks to be added a time, so a List is a reasonable choice.
if (!cbs.contains(cb)) {
cbs.add(cb);
}
if (layoutListener == null) {
ViewTreeObserver observer = view.getViewTreeObserver();
layoutListener = new SizeDeterminerLayoutListener(this);
observer.addOnPreDrawListener(layoutListener);
}
}
這里需要等待ViewTree 的回調(diào),在成功后會(huì)回調(diào)request 的onSizeReady 方法將計(jì)算后的寬高傳入,
SingleRequest onSizeReady
public synchronized void onSizeReady(int width, int height) {
this.stateVerifier.throwIfRecycled();
if (IS_VERBOSE_LOGGABLE) {
this.logV("Got onSizeReady in " + LogTime.getElapsedMillis(this.startTime));
}
if (this.status == SingleRequest.Status.WAITING_FOR_SIZE) {
this.status = SingleRequest.Status.RUNNING;
float sizeMultiplier = this.requestOptions.getSizeMultiplier();
this.width = maybeApplySizeMultiplier(width, sizeMultiplier);
this.height = maybeApplySizeMultiplier(height, sizeMultiplier);
if (IS_VERBOSE_LOGGABLE) {
this.logV("finished setup for calling load in " + LogTime.getElapsedMillis(this.startTime));
}
this.loadStatus = this.engine.load(this.glideContext, this.model, this.requestOptions.getSignature(), this.width, this.height, this.requestOptions.getResourceClass(), this.transcodeClass, this.priority, this.requestOptions.getDiskCacheStrategy(), this.requestOptions.getTransformations(), this.requestOptions.isTransformationRequired(), this.requestOptions.isScaleOnlyOrNoTransform(), this.requestOptions.getOptions(), this.requestOptions.isMemoryCacheable(), this.requestOptions.getUseUnlimitedSourceGeneratorsPool(), this.requestOptions.getUseAnimationPool(), this.requestOptions.getOnlyRetrieveFromCache(), this, this.callbackExecutor);
if (this.status != SingleRequest.Status.RUNNING) {
this.loadStatus = null;
}
if (IS_VERBOSE_LOGGABLE) {
this.logV("finished onSizeReady in " + LogTime.getElapsedMillis(this.startTime));
}
}
}
看到這里整個(gè)加載的過(guò)程我們就已經(jīng)分析完畢了,整個(gè)過(guò)程還是非常復(fù)雜的,但是只要足夠耐心還是能看懂的,