1. 程式人生 > >Glide4.8原始碼拆解(一)入門級介紹

Glide4.8原始碼拆解(一)入門級介紹

前言

Glide是一款功能強大的圖片載入框架,它功能強大,用法簡單且易於擴充套件,同時也是Google推薦的Android平臺圖片載入庫,堪稱優秀。

本章拆解思路

這算是開篇第一章吧,我準備從入口類和簡單的呼叫流程說起,包括但不限於:

  • Glide的構造
  • RequestManager和生命週期監聽
  • Request和配置的收集
  • Target以及觸發非同步載入

Glide物件初始化

從with()說起

為何要從with()方法,明明初始化程式碼在get()方法中:

Glide.java

 public static RequestManager with(@NonNull Context context) {
    return
getRetriever(context).get(context); } public static RequestManager with(@NonNull Activity activity) { return getRetriever(activity).get(activity); } public static RequestManager with(@NonNull FragmentActivity activity) { return getRetriever(activity).get(activity); } public static RequestManager with(@NonNull Fragment fragment) { return
getRetriever(fragment.getActivity()).get(fragment); } public static RequestManager with(@NonNull View view) { return getRetriever(view.getContext()).get(view); } //get方法獲取單例物件 public static Glide get(@NonNull Context context) { if (glide == null) { synchronized (Glide.class) { if
(glide == null) { checkAndInitializeGlide(context); } } } return glide; } //with方法呼叫,獲取RequestManagerRetriever物件 private static RequestManagerRetriever getRetriever(@Nullable Context context) { // Context could be null for other reasons (ie the user passes in null), but in practice it will // only occur due to errors with the Fragment lifecycle. Preconditions.checkNotNull( context, "You cannot start a load on a not yet attached View or a Fragment where getActivity() " + "returns null (which usually occurs when getActivity() is called before the Fragment " + "is attached or after the Fragment is destroyed)."); return Glide.get(context).getRequestManagerRetriever(); } //檢查和初始化Glide 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; } 複製程式碼

with()和get()區別是啥?

兩者最終都會呼叫到get()方法,區別是with()方法會返回一個RequestManager物件,get方法會返回Glide物件,Glide是一個單例模式,在get()中呼叫checkAndInitializeGlide()方法,checkAndInitializeGlide()方法對初始化的判斷

真正執行初始化的呼叫initializeGlide();

解析註解配置項

Glide.java

private static void initializeGlide(@NonNull Context context) {
    initializeGlide(context, new GlideBuilder());//GlideBuilder在此處建立
  }

@SuppressWarnings("deprecation")
private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
    Context applicationContext = context.getApplicationContext();
    GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules();
    List<com.bumptech.glide.module.GlideModule> manifestModules = Collections.emptyList();
    //程式碼1 判斷是否使用清單檔案配置模組
    if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
      manifestModules = new ManifestParser(applicationContext).parse();
    }
    //程式碼2 刪掉排除的類
    if (annotationGeneratedModule != null
        && !annotationGeneratedModule.getExcludedModuleClasses().isEmpty()) {
      Set<Class<?>> excludedModuleClasses =
          annotationGeneratedModule.getExcludedModuleClasses();
      Iterator<com.bumptech.glide.module.GlideModule> iterator = manifestModules.iterator();
      while (iterator.hasNext()) {
        com.bumptech.glide.module.GlideModule current = iterator.next();
        if (!excludedModuleClasses.contains(current.getClass())) {
          continue;
        }
        if (Log.isLoggable(TAG, Log.DEBUG)) {
          Log.d(TAG, "AppGlideModule excludes manifest GlideModule: " + current);
        }
        iterator.remove();
      }
    }

    if (Log.isLoggable(TAG, Log.DEBUG)) {
      for (com.bumptech.glide.module.GlideModule glideModule : manifestModules) {
        Log.d(TAG, "Discovered GlideModule from manifest: " + glideModule.getClass());
      }
    }

    RequestManagerRetriever.RequestManagerFactory factory =
        annotationGeneratedModule != null
            ? annotationGeneratedModule.getRequestManagerFactory() : null;
    builder.setRequestManagerFactory(factory);
    //程式碼3 迴圈呼叫清單配置模組applyOptions方法
    for (com.bumptech.glide.module.GlideModule module : manifestModules) {
      module.applyOptions(applicationContext, builder);
    }
    //程式碼4 呼叫註解配置模組applyOptions方法
    if (annotationGeneratedModule != null) {
      annotationGeneratedModule.applyOptions(applicationContext, builder);
    }
    //程式碼7 關鍵程式碼建立Glide物件
    Glide glide = builder.build(applicationContext);
    //程式碼5 迴圈呼叫清單配置模組registerComponents方法
    for (com.bumptech.glide.module.GlideModule module : manifestModules) {
      module.registerComponents(applicationContext, glide, glide.registry);
    }
    //程式碼6 呼叫註解配置模組registerComponents方法
    if (annotationGeneratedModule != null) {
      annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);
    }
    applicationContext.registerComponentCallbacks(glide);
    Glide.glide = glide;
  }
複製程式碼

initializeGlide還有一個過載的方法,不過被標識過期了,但是核心的邏輯都在這裡啊。

我們發現GlideBuilder在此建立,進入這個過時的方法,該方法先是操作annotationGeneratedModule和manifestModules,註釋在程式碼1~6中有講解,這兩種Module主要是針對Glide的配置,在Glide v3版本中,使用GlideModule和清單檔案中配置,而在V4版本中,廢棄了GlideModule介面,不推薦使用清單檔案配置,建議用AppGlideModule,LibraryGlideModule介面和編譯時註解@GlideModule,具體如何使用清單配置不贅述,借用官方的一個註解配置示例.

例如,v3 版本中 Volley 整合庫的 GlideModule :
public class VolleyGlideModule implements GlideModule {
  @Override
  public void applyOptions(Context context, GlideBuilder builder) {
    // Do nothing.
  }

  @Override
  public void registerComponents(Context context, Registry registry) {
    registry.replace(GlideUrl.class, InputStream.class, new VolleyUrlLoader.Factory(context));
  }
}
在 v4 版本中可以轉換成為一個 LibraryGlideModule :
@GlideModule
public class VolleyLibraryGlideModule extends LibraryGlideModule {
  @Override
  public void registerComponents(Context context, Registry registry) {
    registry.replace(GlideUrl.class, InputStream.class, new VolleyUrlLoader.Factory(context));
  }
}

複製程式碼

解析註解/清單檔案和構造Glide的要有先後順序:

GlideModule的主要功能是讓使用者配置Register和GlideBuilder,在構建Glide之前,將配置選擇新增進去;

接著上面initializeGlide講解,程式碼7處主要是呼叫GlideBuilder.build()方法得到Glide物件,程式碼7必須得在配置模組執行applyOptions之前和執行registerComponents之後呼叫,為什麼?

因為applyOptions(Context context, GlideBuilder builder)方法目的是配置Glide,肯定要執行在builder.build()之前;

registerComponents(Context context, Registry registry)方法配置register,register必須等到Glide建立之後,才能初始化呼叫。

剩下就是GlideBuilder執行build()方法;

GlideBuilder建立預設引數

GlideBuilder.java

Glide build(@NonNull Context context) {
    if (sourceExecutor == null) {
      sourceExecutor = GlideExecutor.newSourceExecutor();
    }
    if (diskCacheExecutor == null) {
      diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
    }
    if (animationExecutor == null) {
      animationExecutor = GlideExecutor.newAnimationExecutor();
    }
    if (memorySizeCalculator == null) {
      memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
    }
    if (connectivityMonitorFactory == null) {
      connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();
    }
    if (bitmapPool == null) {
      int size = memorySizeCalculator.getBitmapPoolSize();
      if (size > 0) {
        bitmapPool = new LruBitmapPool(size);
      } else {
        bitmapPool = new BitmapPoolAdapter();
      }
    }
    if (arrayPool == null) {
      arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes());
    }
    if (memoryCache == null) {
      memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
    }
    if (diskCacheFactory == null) {
      diskCacheFactory = new InternalCacheDiskCacheFactory(context);
    }
    if (engine == null) {
      engine =
          new Engine(
              memoryCache,
              diskCacheFactory,
              diskCacheExecutor,
              sourceExecutor,
              GlideExecutor.newUnlimitedSourceExecutor(),
              GlideExecutor.newAnimationExecutor(),
              isActiveResourceRetentionAllowed);
    }
    RequestManagerRetriever requestManagerRetriever =
        new RequestManagerRetriever(requestManagerFactory);
    return new Glide(
        context,
        engine,
        memoryCache,
        bitmapPool,
        arrayPool,
        requestManagerRetriever,
        connectivityMonitorFactory,
        logLevel,
        defaultRequestOptions.lock(),
        defaultTransitionOptions);
  }
複製程式碼

GlideBuilder主要是為Glide的建立,提供預設配置項和使用者配置項,在上面我們說GlideModule和LibraryGlideModule中applyOptions(Context context, GlideBuilder builder)方法,得到GlideBuilder物件就可以設定相關的配置;詳見GlideBuilder.setXXX()方法;

構造方法和建立Registry

接下來就是真正的呼叫Glide構造方法了

Glide.java

Glide(
      @NonNull Context context,
      @NonNull Engine engine,
      @NonNull MemoryCache memoryCache,
      @NonNull BitmapPool bitmapPool,
      @NonNull ArrayPool arrayPool,
      @NonNull RequestManagerRetriever requestManagerRetriever,
      @NonNull ConnectivityMonitorFactory connectivityMonitorFactory,
      int logLevel,
      @NonNull RequestOptions defaultRequestOptions,
      @NonNull Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions) {
    this.engine = engine;
    this.bitmapPool = bitmapPool;
    this.arrayPool = arrayPool;
    this.memoryCache = memoryCache;
    this.requestManagerRetriever = requestManagerRetriever;
    this.connectivityMonitorFactory = connectivityMonitorFactory;

    DecodeFormat decodeFormat = defaultRequestOptions.getOptions().get(Downsampler.DECODE_FORMAT);
    bitmapPreFiller = new BitmapPreFiller(memoryCache, bitmapPool, decodeFormat);

    final Resources resources = context.getResources();

    registry = new Registry();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
      registry.register(new ExifInterfaceImageHeaderParser());
    }
    registry.register(new DefaultImageHeaderParser());

    Downsampler downsampler = new Downsampler(registry.getImageHeaderParsers(),
        resources.getDisplayMetrics(), bitmapPool, arrayPool);
    ByteBufferGifDecoder byteBufferGifDecoder =
        new ByteBufferGifDecoder(context, registry.getImageHeaderParsers(), bitmapPool, arrayPool);
    ResourceDecoder<ParcelFileDescriptor, Bitmap> parcelFileDescriptorVideoDecoder =
        VideoDecoder.parcel(bitmapPool);
    ByteBufferBitmapDecoder byteBufferBitmapDecoder = new ByteBufferBitmapDecoder(downsampler);
    StreamBitmapDecoder streamBitmapDecoder = new StreamBitmapDecoder(downsampler, arrayPool);
    ResourceDrawableDecoder resourceDrawableDecoder =
        new ResourceDrawableDecoder(context);
    ResourceLoader.StreamFactory resourceLoaderStreamFactory =
        new ResourceLoader.StreamFactory(resources);
    ResourceLoader.UriFactory resourceLoaderUriFactory =
        new ResourceLoader.UriFactory(resources);
    ResourceLoader.FileDescriptorFactory resourceLoaderFileDescriptorFactory =
        new ResourceLoader.FileDescriptorFactory(resources);
    ResourceLoader.AssetFileDescriptorFactory resourceLoaderAssetFileDescriptorFactory =
        new ResourceLoader.AssetFileDescriptorFactory(resources);
    BitmapEncoder bitmapEncoder = new BitmapEncoder(arrayPool);

    BitmapBytesTranscoder bitmapBytesTranscoder = new BitmapBytesTranscoder();
    GifDrawableBytesTranscoder gifDrawableBytesTranscoder = new GifDrawableBytesTranscoder();

    ContentResolver contentResolver = context.getContentResolver();

    registry
        .append(ByteBuffer.class, new ByteBufferEncoder())
        .append(InputStream.class, new StreamEncoder(arrayPool))
        /* Bitmaps */
        .append(Registry.BUCKET_BITMAP, ByteBuffer.class, Bitmap.class, byteBufferBitmapDecoder)
        .append(Registry.BUCKET_BITMAP, InputStream.class, Bitmap.class, streamBitmapDecoder)
        //此處省略好多append方法
          ImageViewTargetFactory imageViewTargetFactory = new ImageViewTargetFactory();
    glideContext = new GlideContext(
            context,
            arrayPool,
            registry,
            imageViewTargetFactory,
            defaultRequestOptions,
            defaultTransitionOptions,
            engine,
            logLevel);
    }
複製程式碼

Glide構造方法除了接受GlideBuilder提供的引數之外,還建立了Registry物件和一堆元件;Registry是整個Glide運轉的核心功能之一,也是我們後面文章即將講到的重點;整理一下Glide構造方法遇到的比較重要的引數: enginememoryCachebitmapPoolarrayPoolrequestManagerRetrieverconnectivityMonitorFactorydefaultRequestOptionsdefaultTransitionOptionsregistryglideContext等。 構造環節就講到這裡,下面從with()方法開始,繼續往下分析;

with()

上文已經說到with一共有五個過載的方法,最終都呼叫Glide.getRetriever()方法得到RequestManagerRetriever物件,然後呼叫RequestManagerRetriever.get()方法,得到RequestManager物件

下面來看一下RequestManagerRetriever的get方法:

RequestManagerRetriever.java

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);
  }
  
  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));
    }
  }
  
  public RequestManager get(@NonNull Fragment fragment) {
    Preconditions.checkNotNull(fragment.getActivity(),
          "You cannot start a load on a fragment before it is attached or after it is destroyed");
    if (Util.isOnBackgroundThread()) {
      return get(fragment.getActivity().getApplicationContext());
    } else {
      FragmentManager fm = fragment.getChildFragmentManager();
      return supportFragmentGet(fragment.getActivity(), fm, fragment, fragment.isVisible());
    }
  }
  
  @SuppressWarnings("deprecation")
  @NonNull
  public RequestManager get(@NonNull Activity activity) {
    if (Util.isOnBackgroundThread()) {
      return get(activity.getApplicationContext());
    } else {
      assertNotDestroyed(activity);
      android.app.FragmentManager fm = activity.getFragmentManager();
      return fragmentGet(
          activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
    }
  }
  
  @SuppressWarnings("deprecation")
  @NonNull
  public RequestManager get(@NonNull View view) {
    if (Util.isOnBackgroundThread()) {
      return get(view.getContext().getApplicationContext());
    }

    Preconditions.checkNotNull(view);
    Preconditions.checkNotNull(view.getContext(),
        "Unable to obtain a request manager for a view without a Context");
    Activity activity = findActivity(view.getContext());
    // The view might be somewhere else, like a service.
    if (activity == null) {
      return get(view.getContext().getApplicationContext());
    }

    // Support Fragments.
    // Although the user might have non-support Fragments attached to FragmentActivity, searching
    // for non-support Fragments is so expensive pre O and that should be rare enough that we
    // prefer to just fall back to the Activity directly.
    if (activity instanceof FragmentActivity) {
      Fragment fragment = findSupportFragment(view, (FragmentActivity) activity);
      return fragment != null ? get(fragment) : get(activity);
    }

    // Standard Fragments.
    android.app.Fragment fragment = findFragment(view, activity);
    if (fragment == null) {
      return get(activity);
    }
    return get(fragment);
  }
複製程式碼

RequestManagerRetriever.get()方法過載,我們分析一下呼叫過程:

  • 當前呼叫執行在子執行緒時,直接把context轉成Application呼叫
  • 當執行在主執行緒時,
  • 如果引數為support下的Fragment或FragmentActivity,呼叫supportFragmentGet(),
  • 如果引數為android包下的Activity或Fragment,呼叫fragmentGet()方法,
  • 如果引數為Application,呼叫getApplicationManager()方法,
  • 如果引數為View,獲取View對應的Context,判斷Context型別,呼叫上面的幾個過載方法;

接下來的呼叫就在getApplicationManager()、supportFragmentGet(),由於fragmentGet()方法已經過時且邏輯和supportFragmentGet()大同小異,所以就不分析它了:

RequestManagerRetriever.java

private RequestManager getApplicationManager(@NonNull Context context) {
    if (applicationManager == null) {
      synchronized (this) {
        if (applicationManager == null) {
          Glide glide = Glide.get(context.getApplicationContext());
          applicationManager =
              factory.build(
                  glide,
                  new ApplicationLifecycle(),
                  new EmptyRequestManagerTreeNode(),
                  context.getApplicationContext());
        }
      }
    }

    return applicationManager;
  }
  
  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) {
      Glide glide = Glide.get(context);
      requestManager =
          factory.build(
              glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
      current.setRequestManager(requestManager);
    }
    return requestManager;
  }
  
  private final RequestManagerFactory factory;
  
  public RequestManagerRetriever(@Nullable RequestManagerFactory factory) {
    this.factory = factory != null ? factory : DEFAULT_FACTORY;
    handler = new Handler(Looper.getMainLooper(), this /* Callback */);
  }
  
  private static final RequestManagerFactory DEFAULT_FACTORY = new RequestManagerFactory() {
    @NonNull
    @Override
    public RequestManager build(@NonNull Glide glide, @NonNull Lifecycle lifecycle,
        @NonNull RequestManagerTreeNode requestManagerTreeNode, @NonNull Context context) {
      return new RequestManager(glide, lifecycle, requestManagerTreeNode, context);
    }
  };
  
  @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);//通過事務新增frg
        fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
        handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
      }
    }
    return current;
  }
複製程式碼

上面兩個方法最後真正建立RequestManager的是factory.build(),factory是RequestManagerFactory中預設的DEFAULT_FACTORY靜態變數;supportFragmentGet()方法中呼叫getSupportRequestManagerFragment方法建立了SupportRequestManagerFragment物件並通過Transaction.add(fragment,tag)方法提交;

所有問題轉換為RequestManager的作用,以及SupportRequestManagerFragment和Lifecycle的意義;

先從SupportRequestManagerFragment分析;

SupportRequestManagerFragment.java

private final ActivityFragmentLifecycle lifecycle;

public SupportRequestManagerFragment() {
    this(new ActivityFragmentLifecycle());
  }

  @VisibleForTesting
  @SuppressLint("ValidFragment")
  public SupportRequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) {
    this.lifecycle = lifecycle;
  }
  
  ActivityFragmentLifecycle getGlideLifecycle() {
    return lifecycle;
  }
  
  @Override
  public void onStart() {
    super.onStart();
    lifecycle.onStart();
  }
  
  @Override
  public void onStop() {
    super.onStop();
    lifecycle.onStop();
  }
  
  @Override
  public void onDestroy() {
    super.onDestroy();
    lifecycle.onDestroy();
    unregisterFragmentWithRoot();
  }
  
複製程式碼

ActivityFragmentLifecycle.java

class ActivityFragmentLifecycle implements Lifecycle {
  private final Set<LifecycleListener> lifecycleListeners =
      Collections.newSetFromMap(new WeakHashMap<LifecycleListener, Boolean>());
  private boolean isStarted;
  private boolean isDestroyed;

  @Override
  public void addListener(@NonNull LifecycleListener listener) {
    lifecycleListeners.add(listener);

    if (isDestroyed) {
      listener.onDestroy();
    } else if (isStarted) {
      listener.onStart();
    } else {
      listener.onStop();
    }
  }

  @Override
  public void removeListener(@NonNull LifecycleListener listener) {
    lifecycleListeners.remove(listener);
  }

  void onStart() {
    isStarted = true;
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
      lifecycleListener.onStart();
    }
  }
  void onStop() {
    isStarted = false;
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
      lifecycleListener.onStop();
    }
  }
  void onDestroy() {
    isDestroyed = true;
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
      lifecycleListener.onDestroy();
    }
  }
}
複製程式碼

LifecycleListener.java

public interface LifecycleListener {
  void onStart();
  void onStop();
  void onDestroy();
}
複製程式碼

Lifecycle.java

public interface Lifecycle {
  void addListener(@NonNull LifecycleListener listener);
  void removeListener(@NonNull LifecycleListener listener);
}
複製程式碼

SupportRequestManagerFragment的構造方法建立了ActivityFragmentLifecycle()物件,然後再fragment對應的onStart()、onStop()、onDestory()方法中呼叫lifecycle的對應方法;

看到這裡有點明白了,Lifecycle是根據Fragment的生命週期而產生;ActivityFragmentLifecycle類持有LifecycleListener泛型的Set集合,在對應的onStart()、onStop()、onDestory()呼叫Set集合中的LifecycleListener對應的方法;

至此我們可以得到一張生命週期的呼叫鏈:SupportRequestManagerFragment->Lifecycle->LifecycleListener;

我們回到對RequestManager的理解,上文分析了RequestManagerRetriever中建立RequestManager,傳遞了Lifecycle引數,下面分析RequestManager的構造和以及它和Lifecycle的關係;

RequestManager.java

//實現了LifecycleListener介面
public class RequestManager implements LifecycleListener{

private final RequestTracker requestTracker;
private final TargetTracker targetTracker = new TargetTracker();

//主執行緒中執行
private final Runnable addSelfToLifecycle = new Runnable() {
    @Override
    public void run() {
      lifecycle.addListener(RequestManager.this);
    }
  };

//構造方法
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 (Util.isOnBackgroundThread()) {
        //在主執行緒中執行
      mainHandler.post(addSelfToLifecycle);
    } else {
        //把自身加入生命週期的監聽中
      lifecycle.addListener(this);
    }
    lifecycle.addListener(connectivityMonitor);

    setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());

    glide.registerRequestManager(this);
  }
  
  @Override
  public void onStart() {
    resumeRequests();
    targetTracker.onStart();//targetTracker監聽
  }
  
  @Override
  public void onStop() {
    pauseRequests();
    targetTracker.onStop();//targetTracker監聽
  }
  
  public void resumeRequests() {
    Util.assertMainThread();
    requestTracker.resumeRequests();//requestTracker監聽
  }
  
  public void pauseRequests() {
    Util.assertMainThread();
    requestTracker.pauseRequests();//requestTracker監聽
  }
  
  @Override
  public void onDestroy() {
    targetTracker.onDestroy();//targetTracker監聽
    for (Target<?> target : targetTracker.getAll()) {
      clear(target);
    }
    targetTracker.clear();//targetTracker監聽
    requestTracker.clearRequests();//requestTracker監聽
    lifecycle.removeListener(this);
    lifecycle.removeListener(connectivityMonitor);
    mainHandler.removeCallbacks(addSelfToLifecycle);
    glide.unregisterRequestManager(this);
  }
}
複製程式碼

RequestManager自身實現了LifecycleListener介面,在構造方法中獲得Lifecycle物件然後把自身addListener,在對應的onStart()、onStop()、onDestory()方法中呼叫呼叫RequestTracker和TargetTracker的對應生命週期方法,完成了生命週期的傳遞;

最終要用到這三個生命週期的對想是RequestTracker和TargetTracker這兩個類,後面會用上他們。

load()

緊接上文,Glide.with()之後獲得RequestManager物件,load()方法自然是RequestManager物件的,RequestManager實現了ModelTypes介面,ModelTypes介面正是這一些列load方法的定義者。

ModelTypes.java

interface ModelTypes<T> {
  @NonNull
  @CheckResult
  T load(@Nullable Bitmap bitmap);

  @NonNull
  @CheckResult
  T load(@Nullable Drawable drawable);

  @NonNull
  @CheckResult
  T load(@Nullable String string);

  @NonNull
  @CheckResult
  T load(@Nullable Uri uri);

  @NonNull
  @CheckResult
  T load(@Nullable File file);

  @NonNull
  @CheckResult
  T load(@RawRes @DrawableRes @Nullable Integer resourceId);

  @Deprecated
  @CheckResult
  T load(@Nullable URL url);

  @NonNull
  @CheckResult
  T load(@Nullable byte[] model);

  @NonNull
  @CheckResult
  @SuppressWarnings("unchecked")
  T load(@Nullable Object model);
}
複製程式碼

ModelTypes定義了8個過載方法load(),支援引數型別:BitmapDrawableStringUriFileIntegerURLbyteObject

它的實現類RequestManager是怎麼做具體的實現 RequestManager.java

public class RequestManager implements LifecycleListener,
    ModelTypes<RequestBuilder<Drawable>> {
    
  public RequestBuilder<Drawable> load(@Nullable Bitmap bitmap) {
    return asDrawable().load(bitmap);
  }
  
  public RequestBuilder<Drawable> load(@Nullable String string) {
    return asDrawable().load(string);
  }
  
  public RequestBuilder<Drawable> load(@Nullable Uri uri) {
    return asDrawable().load(uri);
  }
  
  public RequestBuilder<Drawable> asDrawable() {
    return as(Drawable.class);
  }
  
  public RequestBuilder<GifDrawable> asGif() {
    return as(GifDrawable.class).apply(DECODE_TYPE_GIF);
  }
  
  public <ResourceType> RequestBuilder<ResourceType> as(
      @NonNull Class<ResourceType> resourceClass) {
    return new RequestBuilder<>(glide, this, resourceClass, context);
  }
}

複製程式碼

RequestManager實現了ModelTypes介面並且返回型別為RequestBuilder,重寫了load(xxx)方法,所有的操作都是呼叫asDrawable().load(xxx)方法,真正執行load的還是asDrawable()返回的物件,

除了asDrawable(),還有asGif()、asFile()、as(Class)等方法,其中asGif(),asFile()本質上還是呼叫as(Class)來實現,這個as(Class)方法建立了RequestBuilder物件,所以這個as()方法呼叫就是建立RequestBuilder的,真正load的還是RequestBuilder,

再說說型別,as()方法支援泛型,load()方法支援8種類型(其中包括Object),這意味著,我們可以load()任意自定義型別,返回任意自定義型別的RequestBuilder,這個疑問先放一放,從load()方法追蹤RequestBuilder這個類;

RequestBuilder.java

public RequestBuilder<TranscodeType> load(@Nullable Bitmap bitmap) {
    return loadGeneric(bitmap)
        .apply(diskCacheStrategyOf(DiskCacheStrategy.NONE));
  }
  
  public RequestBuilder<TranscodeType> load(@Nullable Drawable drawable) {
    return loadGeneric(drawable)
        .apply(diskCacheStrategyOf(DiskCacheStrategy.NONE));
  }
  
  public RequestBuilder<TranscodeType> load(@Nullable String string) {
    return loadGeneric(string);
  }
  
  public RequestBuilder<TranscodeType> load(@Nullable Uri uri) {
    return loadGeneric(uri);
  }
  
  public RequestBuilder<TranscodeType> load(@Nullable File file) {
    return loadGeneric(file);
  }
  
  private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
    this.model = model;
    isModelSet = true;
    return this;
  }
  
  public RequestBuilder<TranscodeType> load(@Nullable Object model) {
    return loadGeneric(model);
  }
複製程式碼

從load方法來看,最終都呼叫loadGeneric(Object model),loadGeneric()也只是對model和isModelSet進行賦值,僅此而已,

但是load(Bitmap)和load(Drawable)預設設定了apply(diskCacheStrategyOf(DiskCacheStrategy.NONE),說明直接載入Bitmap和Drawable是不需要DiskCache的,load方法走到這裡就結束了。

load流程總結: 在RequestManager中確定model和SourceType,然後建立RequestBuilder物件,再把model資訊傳遞給RequestBuilder,完成了load流程。

apply()

在Glide實際運用中,簡單的呼叫Glide.with.load.into是遠遠不夠的,我們可能需要更多的配置,比如有佔位圖,圓角剪裁,縮圖等場景,這就要呼叫RequestBuilder.apply()方法,該方法接受一下RequestOptions引數,我們從apply()方法和RequestOptions類來分析:

RequestBuilder.java

public RequestBuilder<TranscodeType> apply(@NonNull RequestOptions requestOptions) {
    Preconditions.checkNotNull(requestOptions);
    this.requestOptions = getMutableOptions().apply(requestOptions);
    return this;
  }
  
  protected RequestOptions getMutableOptions() {
    return defaultRequestOptions == this.requestOptions
        ? this.requestOptions.clone() : this.requestOptions;
  }
複製程式碼

RequestBuilder持有requestOptions,apply()方法主要流程是拿當前的requestOptions,呼叫RequestOptions.apply組合配置;

RequestOptions.java

public RequestOptions apply(@NonNull RequestOptions other) {
    if (isAutoCloneEnabled) {
      return clone().apply(other);
    }

    if (isSet(other.fields, SIZE_MULTIPLIER)) {
      sizeMultiplier = other.sizeMultiplier;
    }
    if (isSet(other.fields, USE_UNLIMITED_SOURCE_GENERATORS_POOL)) {
      useUnlimitedSourceGeneratorsPool = other.useUnlimitedSourceGeneratorsPool;
    }
    if (isSet(other.fields, USE_ANIMATION_POOL)) {
      useAnimationPool = other.useAnimationPool;
    }
    if (isSet(other.fields, DISK_CACHE_STRATEGY)) {
      diskCacheStrategy = other.diskCacheStrategy;
    }
    if (isSet(other.fields, PRIORITY)) {
      priority = other.priority;
    }
    if (isSet(other.fields, ERROR_PLACEHOLDER)) {
      errorPlaceholder = other.errorPlaceholder;
      errorId = 0;
      fields &= ~ERROR_ID;
    }
    if (isSet(other.fields, ERROR_ID)) {
      errorId = other.errorId;
      errorPlaceholder = null;
      fields &= ~ERROR_PLACEHOLDER;
    }
    if (isSet(other.fields, PLACEHOLDER)) {
      placeholderDrawable = other.placeholderDrawable;
      placeholderId = 0;
      fields &= ~PLACEHOLDER_ID;
    }
    if (isSet(other.fields, PLACEHOLDER_ID)) {
      placeholderId = other.placeholderId;
      placeholderDrawable = null;
      fields &= ~PLACEHOLDER;
    }
    if (isSet(other.fields, IS_CACHEABLE)) {
      isCacheable = other.isCacheable;
    }
    if (isSet(other.fields, OVERRIDE)) {
      overrideWidth = other.overrideWidth;
      overrideHeight = other.overrideHeight;
    }
    if (isSet(other.fields, SIGNATURE)) {
      signature = other.signature;
    }
    if (isSet(other.fields, RESOURCE_CLASS)) {
      resourceClass = other.resourceClass;
    }
    if (isSet(other.fields, FALLBACK)) {
      fallbackDrawable = other.fallbackDrawable;
      fallbackId = 0;
      fields &= ~FALLBACK_ID;
    }
    if (isSet(other.fields, FALLBACK_ID)) {
      fallbackId = other.fallbackId;
      fallbackDrawable = null;
      fields &= ~FALLBACK;
    }
    if (isSet(other.fields, THEME)) {
      theme = other.theme;
    }
    if (isSet(other.fields, TRANSFORMATION_ALLOWED)) {
      isTransformationAllowed = other.isTransformationAllowed;
    }
    if (isSet(other.fields, TRANSFORMATION_REQUIRED)) {
      isTransformationRequired = other.isTransformationRequired;
    }
    if (isSet(other.fields, TRANSFORMATION)) {
      transformations.putAll(other.transformations);
      isScaleOnlyOrNoTransform = other.isScaleOnlyOrNoTransform;
    }
    if (isSet(other.fields, ONLY_RETRIEVE_FROM_CACHE)) {
      onlyRetrieveFromCache = other.onlyRetrieveFromCache;
    }
    
    if (!isTransformationAllowed) {
      transformations.clear();
      fields &= ~TRANSFORMATION;
      isTransformationRequired = false;
      fields &= ~TRANSFORMATION_REQUIRED;
      isScaleOnlyOrNoTransform = true;
    }

    fields |= other.fields;
    options.putAll(other.options);

    return selfOrThrowIfLocked();
  }
複製程式碼

注意到RequestOptions有一個int型別成員變數fields,apply方法一直在呼叫isSet()方法做判斷,isSet()邏輯是如果傳入的這個RequestOptions物件other設定了xxx屬性,就替換掉現有的屬性,如果特殊情況再清楚掉其他標誌位,下面著重分析一下fields標誌位;

RequestOptions標誌位

上文提到fields,分析它是用來標誌各個屬性是否被賦值,我們就拿常用了placeholder()方法來分析,placeholder()有兩個過載方法

RequestOptions.java

  private static final int UNSET = -1;
  private static final int SIZE_MULTIPLIER = 1 << 1;
  private static final int DISK_CACHE_STRATEGY = 1 << 2;
  private static final int PRIORITY = 1 << 3;
  private static final int ERROR_PLACEHOLDER = 1 << 4;
  private static final int ERROR_ID = 1 << 5;
  private static final int PLACEHOLDER = 1 << 6;
  private static final int PLACEHOLDER_ID = 1 << 7;
  private static final int IS_CACHEABLE = 1 << 8;
  private static final int OVERRIDE = 1 << 9;
  private static final int SIGNATURE = 1 << 10;
  private static final int TRANSFORMATION = 1 << 11;
  private static final int RESOURCE_CLASS = 1 << 12;
  private static final int FALLBACK = 1 << 13;
  private static final int FALLBACK_ID = 1 << 14;
  private static final int THEME = 1 << 15;
  private static final int TRANSFORMATION_ALLOWED = 1 << 16;
  private static final int TRANSFORMATION_REQUIRED = 1 << 17;
  private static final int USE_UNLIMITED_SOURCE_GENERATORS_POOL = 1 << 18;
  private static final int ONLY_RETRIEVE_FROM_CACHE = 1 << 19;
  private static final int USE_ANIMATION_POOL = 1 << 20;

public RequestOptions placeholder(@Nullable Drawable drawable) {
    if (isAutoCloneEnabled) {
      return clone().placeholder(drawable);
    }

    this.placeholderDrawable = drawable;
    fields |= PLACEHOLDER;//給代表drawable的placeholder標誌位至1

    placeholderId = 0;
    fields &= ~PLACEHOLDER_ID;//給代表id的placeholder標誌位至0

    return selfOrThrowIfLocked();
  }

public RequestOptions placeholder(@DrawableRes int resourceId) {
    if (isAutoCloneEnabled) {
      return clone().placeholder(resourceId);
    }

    this.placeholderId = resourceId;
    fields |= PLACEHOLDER_ID;//給代表id的placeholder標誌位至1

    placeholderDrawable = null;
    fields &= ~PLACEHOLDER;//給代表drawable的placeholder標誌位至0

    return selfOrThrowIfLocked();
  }
  
  private static boolean isSet(int fields, int flag) {
    return (fields & flag) != 0;
  }
  
複製程式碼

placeholder(drawable)和placeholder(resourceId)這兩個方法不能同時對placeholder這一實物產生效果,所以會有fields |= PLACEHOLDER和fields &= ~PLACEHOLDER_ID這樣的程式碼,

系統定義了21個標誌位,通過每個標誌位代表RequestOptions對應屬性的賦值與否,巧妙使用位運算,用一個int型別表示了21個bool邏輯(其實一個int最多能標識32個邏輯),當然這種位運算也是Android原始碼中非常常見的。

RequestOptions的其他方法暫時不過多介紹,我們還是回到主幹呼叫流程,上面講到了load()和apply()方法,這兩個方法主要是收集使用者的配置資訊,真正觸發邏輯的入口是into()方法;

into()流程

RequestBuilder.java

  @NonNull
  public <Y extends Target<TranscodeType>> Y into(@NonNull Y target) {
    return into(target, /*targetListener=*/ null);
  }
  
  @NonNull
  @Synthetic <Y extends Target<TranscodeType>> Y into(
      @NonNull Y target,
      @Nullable RequestListener<TranscodeType> targetListener) {
    return into(target, targetListener, getMutableOptions());
  }
  
  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 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設定request
    target.setRequest(request);
    //跟蹤target和request
    requestManager.track(target, request);
    return target;
  }
  
複製程式碼

RequestBuilder的into()方法程式碼量並不大,主要做了這些事:

  1. 建立Request物件,
  2. 將request設定給target
  3. requestManager跟蹤request和target;

之前一直在說RequestBuilder,顧名思義RequestBuilder是Request的建造者,Request才是真正的大佬;

Request.java

public interface Request {

  void begin();

  void clear();

  boolean isRunning();

  boolean isComplete();

  boolean isResourceSet();

  boolean isCleared();

  boolean isFailed();

  void recycle();

  boolean isEquivalentTo(Request other);
}

複製程式碼

Request不是一個具體的類,它定義了Request該有的方法,其中begin()方法開始一個非同步載入,

Request實現類有三個: ErrorRequestCoordinatorThumbnailRequestCoordinatorSingleRequest,先不細說Request,回到主流程Request的建立是由Builder類完成,RequestBuilder如何構建Request物件的:

在分析Request構建之前,我覺得有必要寫一下Glide縮圖失敗新請求的用法:

縮圖 (Thumbnail) 請求

Glide 的 thumbnail() API 允許你指定一個 RequestBuilder 以與你的主請求並行啟動。thumbnail() 會在主請求載入過程中展示。如果主請求在縮圖請求之前完成,則縮圖請求中的影象將不會被展示。

Glide.with(fragment)
  .load(url)
  .thumbnail(Glide.with(fragment)
    .load(thumbnailUrl))
  .into(imageView);
複製程式碼

thumbnail() 方法有一個簡化版本,它只需要一個 sizeMultiplier 引數。如果你只是想為你的載入相同的圖片,但尺寸為 View 或 Target 的某個百分比的話特別有用:

Glide.with(fragment)
  .load(localUri)
  .thumbnail(/*sizeMultiplier=*/ 0.25f)
  .into(imageView);
複製程式碼

在失敗時開始新的請求

可以使用 error API 來指定一個 RequestBuilder,以在主請求失敗時開始一次新的載入。例如,在請求 primaryUrl 失敗後加載 fallbackUrl

Glide.with(fragment)
  .load(primaryUrl)
  .error(Glide.with(fragment)
      .load(fallbackUrl))
  .into(imageView);
複製程式碼

如果主請求成功完成,這個error RequestBuilder 將不會被啟動。如果你同時指定了一個 thumbnail() 和一個 error() RequestBuilder,則這個後備的 RequestBuilder 將在主請求失敗時啟動,即使縮圖請求成功也是如此。

以上關於縮圖和fallback大部分內容都是來自Glide官方示例。

RequestBuilder.java

  private Float thumbSizeMultiplier;
  RequestBuilder<TranscodeType> errorBuilder;
  private RequestBuilder<TranscodeType> thumbnailBuilder;

  public RequestBuilder<TranscodeType> error(@Nullable RequestBuilder<TranscodeType> errorBuilder) {
    this.errorBuilder = errorBuilder;
    return this;
  }
  
  public RequestBuilder<TranscodeType> thumbnail(
      @Nullable RequestBuilder<TranscodeType> thumbnailRequest) {
    this.thumbnailBuilder = thumbnailRequest;

    return this;
  }
  
  public RequestBuilder<TranscodeType> thumbnail(float sizeMultiplier) {
    if (sizeMultiplier < 0f || sizeMultiplier > 1f) {
      throw new IllegalArgumentException("sizeMultiplier must be between 0 and 1");
    }
    this.thumbSizeMultiplier = sizeMultiplier;

    return this;
  }
複製程式碼

其中thumbnail和error支援傳入一個新的RequestBuilder,而且thumbnail是支援float(0-1.0)引數進行比例等比縮小的f方式。

構建Request流程

接下來看一下Request例項如何被建立處理;

RequestBuilder.java

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);
  }
  
  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) {

    //判斷是否需要建立帶有errorRequest的巢狀Request類
    ErrorRequestCoordinator errorRequestCoordinator = null;
    if (errorBuilder != null) {//意味著這(標記1)呼叫的
      errorRequestCoordinator = new ErrorRequestCoordinator(parentCoordinator);
      parentCoordinator = errorRequestCoordinator;
    }
    //得到可能帶有縮圖巢狀的請求類
    Request mainRequest =
        buildThumbnailRequestRecursive(
            target,
            targetListener,
            parentCoordinator,
            transitionOptions,
            priority,
            overrideWidth,
            overrideHeight,
            requestOptions);
    //不帶error直接返回mainRequest
    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();
    }
    //呼叫當前方法,構建帶error請求 (標記1)
    Request errorRequest = errorBuilder.buildRequestRecursive(
        target,
        targetListener,
        errorRequestCoordinator,
        errorBuilder.transitionOptions,
        errorBuilder.requestOptions.getPriority(),
        errorOverrideWidth,
        errorOverrideHeight,
        errorBuilder.requestOptions);
    errorRequestCoordinator.setRequests(mainRequest, errorRequest);
    return errorRequestCoordinator;
  }
  //建立帶縮圖的請求類
  private Request buildThumbnailRequestRecursive(
      Target<TranscodeType> target,
      RequestListener<TranscodeType> targetListener,
      @Nullable RequestCoordinator parentCoordinator,
      TransitionOptions<?, ? super TranscodeType> transitionOptions,
      Priority priority,
      int overrideWidth,
      int overrideHeight,
      RequestOptions requestOptions) {
      //thumbnailBuilder不為空
    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.requestOptions.isPrioritySet()
          ? thumbnailBuilder.requestOptions.getPriority() : getThumbnailPriority(priority);

      int thumbOverrideWidth = thumbnailBuilder.requestOptions.getOverrideWidth();
      int thumbOverrideHeight = thumbnailBuilder.requestOptions.getOverrideHeight();
      if (Util.isValidDimensions(overrideWidth, overrideHeight)
          && !thumbnailBuilder.requestOptions.isValidOverride()) {
        thumbOverrideWidth = requestOptions.getOverrideWidth();
        thumbOverrideHeight = requestOptions.getOverrideHeight();
      }

      ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
      //源Request
      Request fullRequest =
          obtainRequest(
              target,
              targetListener,
              requestOptions,
              coordinator,
              transitionOptions,
              priority,
              overrideWidth,
              overrideHeight);
      isThumbnailBuilt = true;
      // 縮圖的Request
      Request thumbRequest =
          thumbnailBuilder.buildRequestRecursive(
              target,
              targetListener,
              coordinator,
              thumbTransitionOptions,
              thumbPriority,
              thumbOverrideWidth,
              thumbOverrideHeight,
              thumbnailBuilder.requestOptions);
      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
      Request fullRequest =
          obtainRequest(
              target,
              targetListener,
              requestOptions,
              coordinator,
              transitionOptions,
              priority,
              overrideWidth,
              overrideHeight);
      RequestOptions thumbnailOptions = requestOptions.clone()
          .sizeMultiplier(thumbSizeMultiplier);
        // 縮圖的Request
      Request thumbnailRequest =
          obtainRequest(
              target,
              targetListener,
              thumbnailOptions,
              coordinator,
              transitionOptions,
              getThumbnailPriority(priority),
              overrideWidth,
              overrideHeight);
        //結合在一起
      coordinator.setRequests(fullRequest, thumbnailRequest);
      return coordinator;
    } else {
      //無縮圖,直接返回源Request
      return obtainRequest(
          target,
          targetListener,
          requestOptions,
          parentCoordinator,
          transitionOptions,
          priority,
          overrideWidth,
          overrideHeight);
    }
  }
  
  private Request obtainRequest(
      Target<TranscodeType> target,
      RequestListener<Transcod