Android 進(jìn)階學(xué)習(xí)(十二) Glide源碼學(xué)習(xí)(一) 圖片加載過(guò)程

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ù)雜的,但是只要足夠耐心還是能看懂的,

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容