Glide源碼分析-網(wǎng)絡(luò)圖片加載主流程分析

第一節(jié),我們主要分析
Glide.with(this)
.load(url)
.into(imageView)
這三步,也就是最簡(jiǎn)單的將一個(gè)網(wǎng)絡(luò)圖片展示在ImageView上的三步。

1 Glide.with

Glide.with 重載方法較多

public class Glide implements ComponentCallbacks2 {
    ...
    @NonNull
    public static RequestManager with(@NonNull Context context) {
        return getRetriever(context).get(context);
    }

    @NonNull
    public static RequestManager with(@NonNull Activity activity) {
        return getRetriever(activity).get(activity);
    }

    @NonNull
    public static RequestManager with(@NonNull FragmentActivity activity) {
        return getRetriever(activity).get(activity);
    }

    @NonNull
    public static RequestManager with(@NonNull Fragment fragment) {
        return getRetriever(fragment.getActivity()).get(fragment);
    }

    @SuppressWarnings("deprecation")
    @Deprecated
    @NonNull
    public static RequestManager with(@NonNull android.app.Fragment fragment) {
        return getRetriever(fragment.getActivity()).get(fragment);
    }

    @NonNull
    public static RequestManager with(@NonNull View view) {
        return getRetriever(view.getContext()).get(view);
    }
}

每個(gè)重載方法內(nèi)部都首先調(diào)用getRetriever(@Nullable Context context)方法獲取一個(gè)RequestManagerRetriever對(duì)象,然后調(diào)用其get方法來(lái)返回RequestManager。先來(lái)看Glide.getRetriever

  @NonNull
  private static RequestManagerRetriever getRetriever(@Nullable Context context) {
    // 此處省略對(duì)context判空代碼
    // ...
    
    return Glide.get(context).getRequestManagerRetriever();
  }

方法里調(diào)用了Glide.get(context)創(chuàng)建了一個(gè)Glide,接著調(diào)用 Glide的getRequestManagerRetriever()返回RequestManagerRetriever對(duì)象。看下Glide.get(context)

  @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) {
    // 保證只創(chuàng)建一個(gè)Glide實(shí)例
    if (isInitializing) {
      throw new IllegalStateException("You cannot call Glide.get() in registerComponents(),"
          + " use the provided Glide instance instead");
    }
    isInitializing = true;
    initializeGlide(context);
    isInitializing = false;
  }

這里是創(chuàng)建一個(gè) Glide 單例對(duì)象,具體創(chuàng)建過(guò)程在initializeGlide(context)

  private static void initializeGlide(@NonNull Context context) {
    initializeGlide(context, new GlideBuilder());
  }

  @SuppressWarnings("deprecation")
  private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
    Context applicationContext = context.getApplicationContext();
    
    // 如果有配置@GlideModule注解,那么會(huì)反射構(gòu)造kapt生成的GeneratedAppGlideModuleImpl類
    GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules();
    
    // 如果Impl存在,且允許解析manifest文件,則遍歷manifest中的meta-data,解析出所有的GlideModule類
    List<com.bumptech.glide.module.GlideModule> manifestModules = Collections.emptyList();
    if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
      manifestModules = new ManifestParser(applicationContext).parse();
    }

    // ... 此處省略根據(jù)Impl的黑名單,剔除manifest中的GlideModule類相關(guān)代碼

    // 如果Impl存在,那么設(shè)置為該類的RequestManagerFactory; 否則,設(shè)置為null
    RequestManagerRetriever.RequestManagerFactory factory =
        annotationGeneratedModule != null
            ? annotationGeneratedModule.getRequestManagerFactory() : null;
    builder.setRequestManagerFactory(factory);
    
    // 依次調(diào)用manifest中GlideModule類的applyOptions方法,將配置寫到builder里
    for (com.bumptech.glide.module.GlideModule module : manifestModules) {
      module.applyOptions(applicationContext, builder);
    }
    
    // 寫入Impl的配置,會(huì)覆蓋掉manifest中的配置
    if (annotationGeneratedModule != null) {
      annotationGeneratedModule.applyOptions(applicationContext, builder);
    }
    
    // 調(diào)用GlideBuilder.build方法創(chuàng)建Glide
    Glide glide = builder.build(applicationContext);
    
    // 依次調(diào)用manifest中GlideModule類的registerComponents方法,來(lái)替換Glide的默認(rèn)配置
    for (com.bumptech.glide.module.GlideModule module : manifestModules) {
      module.registerComponents(applicationContext, glide, glide.registry);
    }
    // 調(diào)用Impl中替換Glide配置的方法
    if (annotationGeneratedModule != null) {
        annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);
    }
    
    // 注冊(cè)內(nèi)存管理的回調(diào),因?yàn)镚lide實(shí)現(xiàn)了ComponentCallbacks2接口
    applicationContext.registerComponentCallbacks(glide);
    // 保存glide實(shí)例到靜態(tài)變量中
    Glide.glide = glide;
  }

我們主要分析其中三步主流程,并沒(méi)有 在 AndroidManifest 中配置meta-data,也沒(méi)有配置@GlideModule 注解,所以初始化的代碼可以簡(jiǎn)化如下:

  @SuppressWarnings("deprecation")
  private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
    Context applicationContext = context.getApplicationContext();
    // 調(diào)用GlideBuilder.build方法創(chuàng)建Glide
    Glide glide = builder.build(applicationContext);
    // 注冊(cè)內(nèi)存管理的回調(diào),Glide實(shí)現(xiàn)了ComponentCallbacks2
    applicationContext.registerComponentCallbacks(glide);
    // 保存glide實(shí)例到靜態(tài)變量中
    Glide.glide = glide;
  }

繼續(xù)跟進(jìn)下GlideBuilder.build方法

@NonNull
  Glide build(@NonNull Context context) {
  
    // 此處省略構(gòu)造Glide需要依賴的其他對(duì)象的實(shí)例化代碼
    // ...
    
    RequestManagerRetriever requestManagerRetriever =
        new RequestManagerRetriever(requestManagerFactory);

    return new Glide(
        context,
        engine,
        memoryCache,
        bitmapPool,
        arrayPool,
        requestManagerRetriever,
        connectivityMonitorFactory,
        logLevel,
        defaultRequestOptions.lock(),
        defaultTransitionOptions,
        defaultRequestListeners,
        isLoggingRequestOriginsEnabled);
  }

這里重點(diǎn)看下requestManagerRetriever的初始化,requestManagerRetriever通過(guò)其構(gòu)造器初始化并傳入的requestManagerFactory,然后作為入?yún)魅隚lide構(gòu)造器。跟進(jìn)RequestManagerRetriever構(gòu)造器

  public RequestManagerRetriever(@Nullable RequestManagerFactory factory) {
    this.factory = factory != null ? factory : DEFAULT_FACTORY;
    handler = new Handler(Looper.getMainLooper(), this /* Callback */);
  }

當(dāng)傳進(jìn)來(lái)的factory為null時(shí)會(huì)用默認(rèn)的 DEFAULT_FACTORY

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

DEFAULT_FACTORY 中build方法會(huì)構(gòu)造 RequestManager 對(duì)象。回到 Glide.with 方法中,接著調(diào)用RequestManagerRetriever.get方法,并傳入對(duì)生命周期可感知的入?yún)?,這里的入?yún)⒂?Context、Activity、Fragment、View

@NonNull
private RequestManager getApplicationManager(@NonNull Context context) {
  // Either an application context or we're on a background thread.
  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;
}

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

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

@NonNull
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());
  }

  // 省略 checkNotNull

  // 找出View所在的Fragment或Activity
  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);
}

這些get方法中先判斷是否是后臺(tái)線程,如果是后臺(tái)線程,最終會(huì)直接調(diào)用 getApplicationManager(context) 給 applicationManager 賦值并將其返回,applicationManager是RequestManager類型的對(duì)象。初始化 applicationManager 的代碼如下:

        Glide glide = Glide.get(context.getApplicationContext());
        applicationManager =
            factory.build(
                glide,
                new ApplicationLifecycle(),
                new EmptyRequestManagerTreeNode(),
                context.getApplicationContext());

其中 factory 就是 DEFAULT_FACTORY,DEFAULT_FACTORY 的 build方法會(huì)構(gòu)造并返回的是一個(gè) RequestManager 對(duì)象,所以 applicationManager 初始化代碼可以簡(jiǎn)化如下:

applicationManager =
            RequestManager(
                glide,
                new ApplicationLifecycle(),
                new EmptyRequestManagerTreeNode(),
                context.getApplicationContext());

繼續(xù)回到RequestManagerRetriever.get重載方法,如果當(dāng)前線程不是后臺(tái)線程,get(View)和get(Context)會(huì)根據(jù)情況調(diào)用get(Fragment)或get(FragmentActivity),get(View)最終也會(huì)通過(guò)一系列的操作去找到上層的Fragment或者Activity 然后調(diào)用get(Fragment)或get(FragmentActivity),由于通過(guò)View尋找上層的Fragment或者Activity 的過(guò)程開(kāi)銷相對(duì)較大,不建議傳入View對(duì)象。get(Fragment)和get(FragmentActivity)方法都會(huì)調(diào)用supportFragmentGet方法,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;
  }

Glide會(huì)使用一個(gè)加載目標(biāo)所在的宿主Activity或Fragment的子Fragment來(lái)安全保存一個(gè)RequestManager,而RequestManager被Glide用來(lái)開(kāi)始、停止、管理Glide請(qǐng)求。也就是說(shuō)利用給宿主添加一個(gè)子Fragment來(lái)間接的獲取宿主的生命周期,從而保證Glide請(qǐng)求與生命周期同步。

supportFragmentGet就是創(chuàng)建/獲取這個(gè)子Fragment,即 SupportRequestManagerFragment,并返回 RequestManager 實(shí)例。跟進(jìn)RequestManagerRetriever.getSupportRequestManagerFragment

@NonNull
  private SupportRequestManagerFragment getSupportRequestManagerFragment(
      @NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
    SupportRequestManagerFragment current =
        (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
    if (current == null) {
      current = pendingSupportRequestManagerFragments.get(fm);
      if (current == null) {
        current = new SupportRequestManagerFragment();
        // 對(duì)于fragment來(lái)說(shuō),此方法會(huì)以Activity為host創(chuàng)建另外一個(gè)SupportRequestManagerFragment
        // 作為rootRequestManagerFragment
        // 并會(huì)將current加入到rootRequestManagerFragment的childRequestManagerFragments中
        // 在RequestManager遞歸管理請(qǐng)求時(shí)會(huì)使用到
        current.setParentFragmentHint(parentHint);
        // 如果當(dāng)前頁(yè)面是可見(jiàn)的,那么調(diào)用其lifecycle的onStart方法
        if (isParentVisible) {
          current.getGlideLifecycle().onStart();
        }
        pendingSupportRequestManagerFragments.put(fm, current);
        // 將fragment添加到頁(yè)面中
        fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
        handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
      }
    }
    return current;
  }

如果之前已經(jīng)添加過(guò)SupportRequestManagerFragment則直接返回添加過(guò)的Fragment,否則從 map中獲取獲取,取到了也直接返回,取不到就通過(guò)構(gòu)造器創(chuàng)建一個(gè)對(duì)象,然后將此Fragment添加到宿主Activity或Fragment中。

到這里 Glide.with方法分析完畢,主要就是創(chuàng)建 Glide 單例,并通過(guò)向宿主(Fragment/Activity)添加一個(gè)空的Fragment來(lái)關(guān)聯(lián)宿主的生命周期用來(lái)管理Glide請(qǐng)求,然后返回一個(gè)具體管理Glide請(qǐng)求的 RequestManager 對(duì)象。

2 RequestManager.load

RequestManager.load也有許多重載的方法

@NonNull
@CheckResult
@Override
public RequestBuilder<Drawable> load(@Nullable Bitmap bitmap) {
  return asDrawable().load(bitmap);
}

@NonNull
@CheckResult
@Override
public RequestBuilder<Drawable> load(@Nullable Drawable drawable) {
  return asDrawable().load(drawable);
}

@NonNull
@CheckResult
@Override
public RequestBuilder<Drawable> load(@Nullable String string) {
  return asDrawable().load(string);
}

@NonNull
@CheckResult
@Override
public RequestBuilder<Drawable> load(@Nullable Uri uri) {
  return asDrawable().load(uri);
}

@NonNull
@CheckResult
@Override
public RequestBuilder<Drawable> load(@Nullable File file) {
  return asDrawable().load(file);
}

@SuppressWarnings("deprecation")
@NonNull
@CheckResult
@Override
public RequestBuilder<Drawable> load(@RawRes @DrawableRes @Nullable Integer resourceId) {
  return asDrawable().load(resourceId);
}

@SuppressWarnings("deprecation")
@CheckResult
@Override
@Deprecated
public RequestBuilder<Drawable> load(@Nullable URL url) {
  return asDrawable().load(url);
}

@NonNull
@CheckResult
@Override
public RequestBuilder<Drawable> load(@Nullable byte[] model) {
  return asDrawable().load(model);
}

@NonNull
@CheckResult
@Override
public RequestBuilder<Drawable> load(@Nullable Object model) {
  return asDrawable().load(model);
}

所有的重載方法中都調(diào)用了asDrawable()方法得到一個(gè)RequestBuilder對(duì)象,然后再調(diào)用RequestBuilder.load方法。asDrawable()方法與asGif()、asBitmap()、asFile()等方法一樣,都會(huì)調(diào)用RequestManager.as()方法生成一個(gè)RequestBuilder<ResourceType>對(duì)象,然后再調(diào)用apply方法添加不同的requestOptions,代碼如下:

@NonNull
@CheckResult
public RequestBuilder<Bitmap> asBitmap() {
  return as(Bitmap.class).apply(DECODE_TYPE_BITMAP);
}

@NonNull
@CheckResult
public RequestBuilder<GifDrawable> asGif() {
  return as(GifDrawable.class).apply(DECODE_TYPE_GIF);
}  

@NonNull
@CheckResult
public RequestBuilder<Drawable> asDrawable() {
  return as(Drawable.class);
}

@NonNull
@CheckResult
public RequestBuilder<File> asFile() {
  return as(File.class).apply(skipMemoryCacheOf(true));
}

@NonNull
@CheckResult
public <ResourceType> RequestBuilder<ResourceType> as(
    @NonNull Class<ResourceType> resourceClass) {
  return new RequestBuilder<>(glide, this, resourceClass, context);
}

在RequestBuilder的構(gòu)造器方法方法中將Drawable.class這樣的入?yún)⒈4娴搅藅ranscodeClass變量中。繼續(xù)跟進(jìn)RequestBuilder.load,RequestBuilder.load 也有很多方法的重載:

@NonNull
@CheckResult
@SuppressWarnings("unchecked")
@Override
public RequestBuilder<TranscodeType> load(@Nullable Object model) {
  return loadGeneric(model);
}

@NonNull
@CheckResult
@Override
public RequestBuilder<TranscodeType> load(@Nullable Bitmap bitmap) {
  return loadGeneric(bitmap)
      .apply(diskCacheStrategyOf(DiskCacheStrategy.NONE));
}

@NonNull
@CheckResult
@Override
public RequestBuilder<TranscodeType> load(@Nullable Drawable drawable) {
  return loadGeneric(drawable)
      .apply(diskCacheStrategyOf(DiskCacheStrategy.NONE));
}

@NonNull
@CheckResult
@Override
public RequestBuilder<TranscodeType> load(@Nullable Uri uri) {
  return loadGeneric(uri);
}

@NonNull
@CheckResult
@Override
public RequestBuilder<TranscodeType> load(@Nullable File file) {
  return loadGeneric(file);
}

@NonNull
@CheckResult
@Override
public RequestBuilder<TranscodeType> load(@RawRes @DrawableRes @Nullable Integer resourceId) {
  return loadGeneric(resourceId).apply(signatureOf(ApplicationVersionSignature.obtain(context)));
}

@Deprecated
@CheckResult
@Override
public RequestBuilder<TranscodeType> load(@Nullable URL url) {
  return loadGeneric(url);
}

@NonNull
@CheckResult
@Override
public RequestBuilder<TranscodeType> load(@Nullable byte[] model) {
  RequestBuilder<TranscodeType> result = loadGeneric(model);
  if (!result.isDiskCacheStrategySet()) {
      result = result.apply(diskCacheStrategyOf(DiskCacheStrategy.NONE));
  }
  if (!result.isSkipMemoryCacheSet()) {
    result = result.apply(skipMemoryCacheOf(true /*skipMemoryCache*/));
  }
  return result;
}

@NonNull
private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
  this.model = model;
  isModelSet = true;
  return this;
}

每個(gè)重載方法中都會(huì)調(diào)用loadGeneric保存?zhèn)鬟f的參數(shù)到 model 中并設(shè)置isModelSet=true,部分方法會(huì)apply額外的requestOptions。

總結(jié)一下:RequestManager.load方法中主要就是構(gòu)造RequestBuilder并將load的資源保存到RequestBuilder中的 model 變量中。

3 RequestBuilder.into

RequestBuilder.into方法的重載也比較多,我們常用的是into(imageView),代碼如下:

@NonNull
  public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
    Util.assertMainThread();
    Preconditions.checkNotNull(view);

    BaseRequestOptions<?> requestOptions = this;
    
    // 若沒(méi)有指定transform,isTransformationSet()為false
    // isTransformationAllowed()一般為true,除非主動(dòng)調(diào)用了dontTransform()方法
    if (!requestOptions.isTransformationSet()
        && requestOptions.isTransformationAllowed()
        && view.getScaleType() != null) {
      
      // 根據(jù)ImageView的ScaleType設(shè)置不同的 downsample 和transform 選項(xiàng)對(duì)圖片進(jìn)行剪裁
      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());
  }

into(ImageView)方法里面會(huì)先判斷需不需要對(duì)圖片進(jìn)行裁切,然后調(diào)用into重載方法。into重載方法第一個(gè)參數(shù)glideContext.buildImageViewTarget(view, transcodeClass)代碼如下:

// GlideContext
@NonNull
public <X> ViewTarget<ImageView, X> buildImageViewTarget(
    @NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {
  // imageViewTargetFactory是ImageViewTargetFactory的一個(gè)實(shí)例
  // transcodeClass在RequestManager.load方法中確定了,就是Drawable.class
  return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
}

// 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)) {
    // 返回的是(ViewTarget<ImageView, Drawable>) new DrawableImageViewTarget(view);
    return (ViewTarget<ImageView, Z>) new DrawableImageViewTarget(view);
  } else {
    throw new IllegalArgumentException(
        "Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
  }
}

因?yàn)槲覀冞@里要轉(zhuǎn)碼的類型為:Drawable.class,所以buildTarget返回的是DrawableImageViewTarget對(duì)象,所以第一個(gè)參數(shù)等價(jià)于

(ViewTarget<ImageView, Drawable>) new DrawableImageViewTarget(view)

第四個(gè)參數(shù)Executors.mainThreadExecutor()是一個(gè)Executor,內(nèi)部使用MainLooper的Handler,當(dāng)執(zhí)行Executor.execute(Runnable)方法時(shí)將Runnable使用此 Handler post 出去。

  /** Posts executions to the main thread. */
  public static Executor mainThreadExecutor() {
    return MAIN_THREAD_EXECUTOR;
  }

    private static final Executor MAIN_THREAD_EXECUTOR =
      new Executor() {
        private final Handler handler = new Handler(Looper.getMainLooper());

        @Override
        public void execute(@NonNull Runnable command) {
          handler.post(command);
        }
    };

分析完了參數(shù),繼續(xù)分析into 重載方法內(nèi)部實(shí)現(xiàn)

private <Y extends Target<TranscodeType>> Y into(
    @NonNull Y target,
    @Nullable RequestListener<TranscodeType> targetListener,
    BaseRequestOptions<?> options,
    Executor callbackExecutor) {

  if (!isModelSet) {
    throw new IllegalArgumentException("You must call #load() before calling #into()");
  }

  // 創(chuàng)建了一個(gè)SingleRequest
  Request request = buildRequest(target, targetListener, options, callbackExecutor);

  // 這里會(huì)判斷需不需要重新開(kāi)始任務(wù)
  // 如果當(dāng)前request和target上之前的request previous相等
  // 且設(shè)置了忽略內(nèi)存緩存或previous還沒(méi)有完成
  // 那么會(huì)進(jìn)入if分支
  Request previous = target.getRequest();
  if (request.isEquivalentTo(previous)
      && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
    request.recycle();
    
    // 如果正在運(yùn)行,就不管它;如果已經(jīng)失敗了,就重新開(kāi)始
    if (!Preconditions.checkNotNull(previous).isRunning()) {
        previous.begin();
    }
    return target;
  }

  // 如果不能復(fù)用previous
  // 先清除target上之前的Request
  requestManager.clear(target);
  // 將Request作為tag設(shè)置到view中
  target.setRequest(request);
  // 真正開(kāi)始網(wǎng)絡(luò)圖片的加載
  requestManager.track(target, request);

  return target;
}

先看一下buildRequest(target, targetListener, options, callbackExecutor)如何創(chuàng)建SingleRequest,方法調(diào)用鏈為:buildRequest->buildRequestRecursive->buildThumbnailRequestRecursive->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);
}

最終通過(guò)SingleRequest.obtain方法傳遞參數(shù)構(gòu)建SingleRequest對(duì)象。繼續(xù)回到into重載方法中調(diào)用requestManager.track(target, request)進(jìn)行網(wǎng)絡(luò)圖片的加載。

  synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
    targetTracker.track(target);
    requestTracker.runRequest(request);
  }

targetTracker成員變量在聲明的時(shí)候直接初始化為TargetTracker類的無(wú)參數(shù)實(shí)例,該類的作用是保存所有的Target并向它們轉(zhuǎn)發(fā)生命周期事件.requestTracker在RequestManager的構(gòu)造器中傳入了new RequestTracker(),該類的作用管理所有狀態(tài)的請(qǐng)求。繼續(xù)跟進(jìn)requestTracker.runRequest(request)

  /**
   * Starts tracking the given request.
   */
  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);
    }
  }

isPaused默認(rèn)為false,只有調(diào)用了RequestTracker.pauseRequests或RequestTracker.pauseAllRequests后才會(huì)為true。因此,下面會(huì)執(zhí)行request.begin()方法,這里的request就是在into重載方法里面構(gòu)造出來(lái)的 SingleRequest,跟進(jìn)SingleRequest.begin

@Override
  public synchronized void begin() {
  
    //...
    
    // 如果model為空,會(huì)調(diào)用監(jiān)聽(tīng)器的onLoadFailed處理
    // 若無(wú)法處理,則展示失敗時(shí)的占位圖
    if (model == null) {
      ...
      onLoadFailed(new GlideException("Received null model"), logLevel);
      return;
    }

    if (status == Status.RUNNING) {
      throw new IllegalArgumentException("Cannot restart a running request");
    }

    // 如果已經(jīng)加載過(guò),再次在相同的目標(biāo)或視圖中加載相同的請(qǐng)求,在重新來(lái)加載前清除View或Target
    if (status == Status.COMPLETE) {
      onResourceReady(resource, DataSource.MEMORY_CACHE);
      return;
    }

    // 如果指定了overrideWidth和overrideHeight,那么直接調(diào)用onSizeReady方法
    // 否則會(huì)獲取ImageView的寬、高,然后調(diào)用onSizeReady方法
    // 在該方法中會(huì)創(chuàng)建圖片加載的Job并開(kāi)始執(zhí)行
    status = Status.WAITING_FOR_SIZE;
    if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
      onSizeReady(overrideWidth, overrideHeight);
    } else {
      target.getSize(this);
    }

    // 顯示加載中的占位符
    if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)
        && canNotifyStatusChanged()) {
      target.onLoadStarted(getPlaceholderDrawable());
    }
    if (IS_VERBOSE_LOGGABLE) {
      logV("finished run method in " + LogTime.getElapsedMillis(startTime));
    }
  }

如果 model == null會(huì)調(diào)用onLoadFailed方法,在其內(nèi)部會(huì)調(diào)用監(jiān)聽(tīng)器的onLoadFailed處理,若無(wú)法處理,則展示失敗時(shí)的占位圖。如果指定了overrideWidth和overrideHeight,那么直接調(diào)用onSizeReady方法,否則會(huì)獲取ImageView的寬、高,然后調(diào)用onSizeReady方法,在該方法中會(huì)創(chuàng)建圖片加載的Job并開(kāi)始執(zhí)行。我們先來(lái)看下 SingleRequest.onSizeReady:

@Override
  public synchronized void onSizeReady(int width, int height) {
    
    ...
    
    // 在SingleRequest.begin方法中已經(jīng)將status設(shè)置為WAITING_FOR_SIZE狀態(tài)了
    if (status != Status.WAITING_FOR_SIZE) {
      return;
    }
    
    // 設(shè)置狀態(tài)為RUNNING
    status = Status.RUNNING;

    // 將原始尺寸與0~1之間的系數(shù)相乘,取最接近的整數(shù)值,得到新的尺寸
    float sizeMultiplier = requestOptions.getSizeMultiplier();
    this.width = maybeApplySizeMultiplier(width, sizeMultiplier);
    this.height = maybeApplySizeMultiplier(height, sizeMultiplier);

    ...
    
    loadStatus =
        engine.load(
            glideContext,
            model,
            requestOptions.getSignature(),
            this.width,
            this.height,
            requestOptions.getResourceClass(),
            transcodeClass,
            priority,
            requestOptions.getDiskCacheStrategy(),
            requestOptions.getTransformations(),
            requestOptions.isTransformationRequired(),
            requestOptions.isScaleOnlyOrNoTransform(),
            requestOptions.getOptions(),
            requestOptions.isMemoryCacheable(),
            requestOptions.getUseUnlimitedSourceGeneratorsPool(),
            requestOptions.getUseAnimationPool(),
            requestOptions.getOnlyRetrieveFromCache(),
            this,
            callbackExecutor);

    ...
  }

最后會(huì)調(diào)用engine.load方法,Engine是負(fù)責(zé)加載,管理active、cached狀態(tài)資源的類。在GlideBuilder.build中創(chuàng)建Glide時(shí),若沒(méi)有主動(dòng)設(shè)置engine,會(huì)使用下面的參數(shù)進(jìn)行創(chuàng)建

if (sourceExecutor == null) {
  sourceExecutor = GlideExecutor.newSourceExecutor();
}

if (diskCacheExecutor == null) {
  diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
}

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

繼續(xù)跟進(jìn)Engine.load方法

public synchronized <R> LoadStatus load(
      GlideContext glideContext,
      Object model,
      Key signature,
      int width,
      int height,
      Class<?> resourceClass,
      Class<R> transcodeClass,
      Priority priority,
      DiskCacheStrategy diskCacheStrategy,
      Map<Class<?>, Transformation<?>> transformations,
      boolean isTransformationRequired,
      boolean isScaleOnlyOrNoTransform,
      Options options,
      boolean isMemoryCacheable,
      boolean useUnlimitedSourceExecutorPool,
      boolean useAnimationPool,
      boolean onlyRetrieveFromCache,
      ResourceCallback cb,
      Executor callbackExecutor) {
    long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0;

    // 根據(jù)部分參數(shù)生成 key 
    EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations,
        resourceClass, transcodeClass, options);

    // 從active資源中進(jìn)行加載
    EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
    if (active != null) {
      cb.onResourceReady(active, DataSource.MEMORY_CACHE);
      if (VERBOSE_IS_LOGGABLE) {
        logWithTimeAndKey("Loaded resource from active resources", startTime, key);
      }
      return null;
    }

    // 從內(nèi)存cache資源中進(jìn)行加載
    EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
    if (cached != null) {
      cb.onResourceReady(cached, DataSource.MEMORY_CACHE);
      if (VERBOSE_IS_LOGGABLE) {
        logWithTimeAndKey("Loaded resource from cache", startTime, key);
      }
      return null;
    }

    // 從正在進(jìn)行的jobs中進(jìn)行加載
    EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
    if (current != null) {
      current.addCallback(cb, callbackExecutor);
      if (VERBOSE_IS_LOGGABLE) {
        logWithTimeAndKey("Added to existing load", startTime, key);
      }
      return new LoadStatus(cb, current);
    }

    // 構(gòu)建出一個(gè)EngineJob
    EngineJob<R> engineJob =
        engineJobFactory.build(
            key,
            isMemoryCacheable,
            useUnlimitedSourceExecutorPool,
            useAnimationPool,
            onlyRetrieveFromCache);

    // 構(gòu)建出一個(gè)DecodeJob,該類實(shí)現(xiàn)了Runnable接口
    DecodeJob<R> decodeJob =
        decodeJobFactory.build(
            glideContext,
            model,
            key,
            signature,
            width,
            height,
            resourceClass,
            transcodeClass,
            priority,
            diskCacheStrategy,
            transformations,
            isTransformationRequired,
            isScaleOnlyOrNoTransform,
            onlyRetrieveFromCache,
            options,
            engineJob);

    // 根據(jù)engineJob.onlyRetrieveFromCache的值是否為true
    // 將engineJob保存到onlyCacheJobs或者jobs HashMap中
    jobs.put(key, engineJob);

    // 添加資源加載狀態(tài)回調(diào),參數(shù)會(huì)包裝成ResourceCallbackAndExecutor類型
    // 并保存到ResourceCallbacksAndExecutors.callbacksAndExecutors中
    engineJob.addCallback(cb, callbackExecutor);
    
    // 開(kāi)始執(zhí)行decodeJob任務(wù)
    engineJob.start(decodeJob);

    ...
    
    return new LoadStatus(cb, engineJob);
  }

Engine.load方法中會(huì)以一些參數(shù)作為key,依次從active狀態(tài)、cached狀態(tài)和進(jìn)行中的 jobs 里尋找。若沒(méi)有找到,則會(huì)創(chuàng)建對(duì)應(yīng)的job并開(kāi)始執(zhí)行。engineJobFactorydecodeJobFactory 需要注意的是里面使用了對(duì)象池 Pools.Pool 來(lái)復(fù)用 Job對(duì)象內(nèi)存,Pools.Pool里面通過(guò)Object[]來(lái)保存Job。繼續(xù)跟進(jìn) engineJob.start(decodeJob):

  // EngineJob
  public synchronized void start(DecodeJob<R> decodeJob) {
    this.decodeJob = decodeJob;
    GlideExecutor executor = decodeJob.willDecodeFromCache()
        ? diskCacheExecutor
        : getActiveSourceExecutor();
    executor.execute(decodeJob);
  }

由于我們沒(méi)有配置緩存策略,默認(rèn)會(huì)使用緩存,所以decodeJob.willDecodeFromCache()為true,那么就使用diskCacheExecutor 來(lái)執(zhí)行decodeJob。diskCacheExecutor 默認(rèn)值為GlideExecutor.newDiskCacheExecutor(),這是類似于一個(gè)SingleThreadExecutor的線程池,這里使用了設(shè)計(jì)模式中的代理模式:

/**
 * A prioritized {@link ThreadPoolExecutor} for running jobs in Glide.
 */
public final class GlideExecutor implements ExecutorService {
  private static final String DEFAULT_DISK_CACHE_EXECUTOR_NAME = "disk-cache";
  private static final int DEFAULT_DISK_CACHE_EXECUTOR_THREADS = 1;

  private final ExecutorService delegate;

  public static GlideExecutor newDiskCacheExecutor() {
    return newDiskCacheExecutor(
        DEFAULT_DISK_CACHE_EXECUTOR_THREADS,
        DEFAULT_DISK_CACHE_EXECUTOR_NAME,
        UncaughtThrowableStrategy.DEFAULT);
  }

  public static GlideExecutor newDiskCacheExecutor(
      int threadCount, String name, UncaughtThrowableStrategy uncaughtThrowableStrategy) {
    return new GlideExecutor(
        new ThreadPoolExecutor(
            threadCount /* corePoolSize */,
            threadCount /* maximumPoolSize */,
            0 /* keepAliveTime */,
            TimeUnit.MILLISECONDS,
            new PriorityBlockingQueue<Runnable>(),
            new DefaultThreadFactory(name, uncaughtThrowableStrategy, true)));
  }

  @VisibleForTesting
  GlideExecutor(ExecutorService delegate) {
    this.delegate = delegate;
  }

  @Override
  public void execute(@NonNull Runnable command) {
    delegate.execute(command);
  }

  @NonNull
  @Override
  public Future<?> submit(@NonNull Runnable task) {
    return delegate.submit(task);
  }
  ...
}

至此,decodeJob已經(jīng)提交到了線程池中?;氐絊ingleRequest.begin 繼續(xù)跟進(jìn)后面的代碼

if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)
    && canNotifyStatusChanged()) {
  target.onLoadStarted(getPlaceholderDrawable());
}

由于此時(shí)status == Status.RUNNING為true,現(xiàn)在開(kāi)始展示placeholder。

前面我們已經(jīng)將decodeJob已經(jīng)提交到了線程池中,那么繼續(xù)分析DecodeJob.run方法

@Override
  public void run() {
    ...
    try {
      if (isCancelled) {
        notifyFailed();
        return;
      }
      
      runWrapped();
    } catch (CallbackException e) {
      throw e;
    } catch (Throwable t) {
      ...
      throw t;
    } finally {
       ...
    }
  }

方法里面主要就是執(zhí)行了 runWrapped 方法

  private void runWrapped() {
    switch (runReason) {
      case INITIALIZE:
        stage = getNextStage(Stage.INITIALIZE);
        currentGenerator = getNextGenerator();
        runGenerators();
        break;
      case SWITCH_TO_SOURCE_SERVICE:
        ...
        break;
      case DECODE_DATA:
        ...
        break;
      ...
    }
  }

runReason在DecodeJob.init方法中被初始化為INITIALIZE,所以我們需要關(guān)注的的代碼為

// 獲取下一個(gè)狀態(tài)RESOURCE_CACHE并賦值給stage
stage = getNextStage(Stage.INITIALIZE);
// getNextGenerator()返回的是 ResourceCacheGenerator
currentGenerator = getNextGenerator();
runGenerators();
  private Stage getNextStage(Stage current) {
    switch (current) {
      case INITIALIZE:
        return diskCacheStrategy.decodeCachedResource()
            ? Stage.RESOURCE_CACHE : getNextStage(Stage.RESOURCE_CACHE);
      case RESOURCE_CACHE:
        ...
      case DATA_CACHE:
        ...
      case SOURCE:
      case FINISHED:
        ...
      ...
    }
  }
  
  private DataFetcherGenerator getNextGenerator() {
    switch (stage) {
      case RESOURCE_CACHE:
        return new ResourceCacheGenerator(decodeHelper, this);
      case DATA_CACHE:
        return new DataCacheGenerator(decodeHelper, this);
      case SOURCE:
        return new SourceGenerator(decodeHelper, this);
      case FINISHED:
        return null;
      default:
        throw new IllegalStateException("Unrecognized stage: " + stage);
    }
  }

stage 的狀態(tài)被修改為 RESOURCE_CACHE,currentGenerator 為 ResourceCacheGenerator,繼續(xù)跟進(jìn) runGenerators 方法:

  private void runGenerators() {
    currentThread = Thread.currentThread();
    startFetchTime = LogTime.getLogTime();
    boolean isStarted = false;
    while (!isCancelled && currentGenerator != null
        && !(isStarted = currentGenerator.startNext())) {
      stage = getNextStage(stage);
      currentGenerator = getNextGenerator();

      if (stage == Stage.SOURCE) {
        reschedule();
        return;
      }
    }
    // We've run out of stages and generators, give up.
    if ((stage == Stage.FINISHED || isCancelled) && !isStarted) {
      notifyFailed();
    }

  }

該方法中會(huì)依次調(diào)用各個(gè)狀態(tài)生成的 DataFetcherGenerator 的 startNext() 嘗試fetch數(shù)據(jù),取數(shù)據(jù)成功了該方法就結(jié)束。若狀態(tài)到了Stage.FINISHED 或 job 被取消,且所有狀態(tài)的DataFetcherGenerator.startNext()都無(wú)法滿足條件,則調(diào)用SingleRequest.onLoadFailed進(jìn)行錯(cuò)誤處理。根據(jù)getNextGenerator()方法代碼可發(fā)現(xiàn):DataFetcherGenerator 有三個(gè)子類:

  • ResourceCacheGenerator
    獲取downsample、transform后的資源文件的緩存文件

  • DataCacheGenerator
    獲取原始的沒(méi)有修改過(guò)的資源文件的緩存文件

  • SourceGenerator
    獲取原始源數(shù)據(jù)

先跟進(jìn)下 ResourceCacheGenerator.startNext:

@Override
  public boolean startNext() {
    // list里面只有一個(gè)GlideUrl對(duì)象
    List<Key> sourceIds = helper.getCacheKeys();
    if (sourceIds.isEmpty()) {
      return false;
    }
    // 獲得了三個(gè)可以到達(dá)的registeredResourceClasses
    // GifDrawable、Bitmap、BitmapDrawable
    List<Class<?>> resourceClasses = helper.getRegisteredResourceClasses();
    if (resourceClasses.isEmpty()) {
      if (File.class.equals(helper.getTranscodeClass())) {
        return false;
      }
      throw new IllegalStateException(
         "Failed to find any load path from " + helper.getModelClass() + " to "
             + helper.getTranscodeClass());
    }
    
    // 遍歷sourceIds中的每一個(gè)key、resourceClasses中每一個(gè)class,以及其他的一些值組成key
    // 嘗試在磁盤緩存中以key找到緩存文件
    while (modelLoaders == null || !hasNextModelLoader()) {
      resourceClassIndex++;
      if (resourceClassIndex >= resourceClasses.size()) {
        sourceIdIndex++;
        if (sourceIdIndex >= sourceIds.size()) {
          return false;
        }
        resourceClassIndex = 0;
      }

      Key sourceId = sourceIds.get(sourceIdIndex);
      Class<?> resourceClass = resourceClasses.get(resourceClassIndex);
      Transformation<?> transformation = helper.getTransformation(resourceClass);
      // PMD.AvoidInstantiatingObjectsInLoops Each iteration is comparatively expensive anyway,
      // we only run until the first one succeeds, the loop runs for only a limited
      // number of iterations on the order of 10-20 in the worst case.
      currentKey =
          new ResourceCacheKey(// NOPMD AvoidInstantiatingObjectsInLoops
              helper.getArrayPool(),
              sourceId,
              helper.getSignature(),
              helper.getWidth(),
              helper.getHeight(),
              transformation,
              resourceClass,
              helper.getOptions());
      cacheFile = helper.getDiskCache().get(currentKey);
      
      // 如果找到了緩存文件,循環(huán)條件則會(huì)為false,退出循環(huán)
      if (cacheFile != null) {
        sourceKey = sourceId;
        // 1. 找出注入時(shí)以File.class為modelClass的注入代碼
        // 2. 調(diào)用所有注入的factory.build方法得到ModelLoader
        // 3 .過(guò)濾掉不可能處理model的ModelLoader
        // 此時(shí)的modelLoaders值為:
        // [ByteBufferFileLoader, FileLoader, FileLoader, UnitModelLoader]
        modelLoaders = helper.getModelLoaders(cacheFile);
        modelLoaderIndex = 0;
      }
    }

    // 如果找到了緩存文件,hasNextModelLoader()方法則會(huì)為true,可以執(zhí)行循環(huán)
    // 沒(méi)有找到緩存文件,則不會(huì)進(jìn)入循環(huán),會(huì)直接返回false
    loadData = null;
    boolean started = false;
    while (!started && hasNextModelLoader()) {
      ModelLoader<File, ?> modelLoader = modelLoaders.get(modelLoaderIndex++);
      // 在循環(huán)中會(huì)依次判斷某個(gè)ModelLoader能不能加載此文件
      loadData = modelLoader.buildLoadData(cacheFile,
          helper.getWidth(), helper.getHeight(), helper.getOptions());
      if (loadData != null && helper.hasLoadPath(loadData.fetcher.getDataClass())) {
        started = true;
        
        // 如果某個(gè)ModelLoader可以,那么就調(diào)用其fetcher進(jìn)行加載數(shù)據(jù)
        // 加載成功或失敗會(huì)通知自身
        loadData.fetcher.loadData(helper.getPriority(), this);
      }
    }

    return started;
  }

如果已經(jīng)找到一個(gè)一條可以加載的路徑,那么就調(diào)用此fetcher.loadData方法進(jìn)行加載。同時(shí),該方法ResourceCacheGenerator.startNext返回true,這就意味著DecodeJob無(wú)需在嘗試另外的 DataFetcherGenerator 進(jìn)行加載,整個(gè)into過(guò)程已經(jīng)大致完成,剩下的就是等待資源加載完畢后觸發(fā)回調(diào)。續(xù)分析 loadData.fetcher.loadData(helper.getPriority(), this),這里的 fetcher 是 ByteBufferFetcher:

    // ByteBufferFetcher
    @Override
    public void loadData(@NonNull Priority priority,
        @NonNull DataCallback<? super ByteBuffer> callback) {
      ByteBuffer result;
      try {
        // 這里的file就是緩存下來(lái)的source file
        result = ByteBufferUtil.fromFile(file);
      } catch (IOException e) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
          Log.d(TAG, "Failed to obtain ByteBuffer for file", e);
        }
        callback.onLoadFailed(e);
        return;
      }

      callback.onDataReady(result);
    }

ByteBufferUtil.fromFile使用了RandomAccessFile和FileChannel進(jìn)行文件操作。如果操作失敗,調(diào)用callback.onLoadFailed(e)通知ResourceCacheGenerator類,該類會(huì)將操作轉(zhuǎn)發(fā)給DecodeJob;callback.onDataReady操作類似。這樣程序就回到了DecodeJob回調(diào)方法中了。

但是按照我們的流程,第一次加載時(shí)沒(méi)有緩存的,所以 ResourceCacheGenerator.startNext 中找不到緩存文件,繼續(xù)交給DataCacheGenerator.startNext 處理:

public boolean startNext() {
    while (modelLoaders == null || !hasNextModelLoader()) {
      sourceIdIndex++;
      if (sourceIdIndex >= cacheKeys.size()) {
        return false;
      }

      Key sourceId = cacheKeys.get(sourceIdIndex);
      // PMD.AvoidInstantiatingObjectsInLoops The loop iterates a limited number of times
      // and the actions it performs are much more expensive than a single allocation.
      @SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
      Key originalKey = new DataCacheKey(sourceId, helper.getSignature());
      cacheFile = helper.getDiskCache().get(originalKey);
      if (cacheFile != null) {
        this.sourceKey = sourceId;
        modelLoaders = helper.getModelLoaders(cacheFile);
        modelLoaderIndex = 0;
      }
    }

    loadData = null;
    boolean started = false;
    while (!started && hasNextModelLoader()) {
      ModelLoader<File, ?> modelLoader = modelLoaders.get(modelLoaderIndex++);
      loadData =
          modelLoader.buildLoadData(cacheFile, helper.getWidth(), helper.getHeight(),
              helper.getOptions());
      if (loadData != null && helper.hasLoadPath(loadData.fetcher.getDataClass())) {
        started = true;
        loadData.fetcher.loadData(helper.getPriority(), this);
      }
    }
    return started;
  }

由于第一次加載,本地緩存沒(méi)有,接著交給最后一個(gè) SourceGenerator.startNext 來(lái)處理

@Override
  public boolean startNext() {
  
    // 首次運(yùn)行dataToCache為null
    if (dataToCache != null) {
      Object data = dataToCache;
      dataToCache = null;
      cacheData(data);
    }

    // 首次運(yùn)行sourceCacheGenerator為null
    if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {
      return true;
    }
    sourceCacheGenerator = null;

    loadData = null;
    boolean started = false;
    while (!started && hasNextModelLoader()) {
      loadData = helper.getLoadData().get(loadDataListIndex++);
      if (loadData != null
          && (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
          || helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
        started = true;
        loadData.fetcher.loadData(helper.getPriority(), this);
      }
    }
    return started;
  }

helper.getLoadData()的值在ResourceCacheGenerator中就已經(jīng)被獲取并緩存下來(lái)了,這是一個(gè)MultiModelLoader對(duì)象生成的LoadData對(duì)象,LoadData對(duì)象里面有兩個(gè)fetcher。

遍歷LoadData list,找出符合條件的LoadData,然后調(diào)用loadData.fetcher.loadData加載數(shù)據(jù)。若loadData不為null,會(huì)判斷Glide的緩存策略是否可以緩存此數(shù)據(jù)源,或者是否有加載路徑。MultiModelLoader里面的fetcher是MultiFetcher,我們來(lái)看下MultiFetcher.loadData:

    // MultiFetcher
    @Override
    public void loadData(
        @NonNull Priority priority, @NonNull DataCallback<? super Data> callback) {
      this.priority = priority;
      this.callback = callback;
      exceptions = throwableListPool.acquire();
      // 類型是HttpUrlFetcher
      fetchers.get(currentIndex).loadData(priority, this);

      if (isCancelled) {
        cancel();
      }
    }

繼續(xù)跟進(jìn) HttpUrlFetcher.loadData

  // HttpUrlFetcher
  @Override
  public void loadData(@NonNull Priority priority,
      @NonNull DataCallback<? super InputStream> callback) {
    long startTime = LogTime.getLogTime();
    try {
      InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
      callback.onDataReady(result);
    } catch (IOException e) {
      if (Log.isLoggable(TAG, Log.DEBUG)) {
        Log.d(TAG, "Failed to load data for url", e);
      }
      callback.onLoadFailed(e);
    } finally {
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        Log.v(TAG, "Finished http url fetcher fetch in " + LogTime.getElapsedMillis(startTime));
      }
    }
  }

這里將請(qǐng)求操作放到了loadDataWithRedirects方法中,然后將請(qǐng)求結(jié)果通過(guò)回調(diào)返回上一層也就是MultiFetcher中。跟進(jìn)HttpUrlFetcher.loadDataWithRedirects:

// HttpUrlFetcher
private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl,
      Map<String, String> headers) throws IOException {
      
    // 檢查重定向次數(shù)
    if (redirects >= MAXIMUM_REDIRECTS) {
      throw new HttpException("Too many (> " + MAXIMUM_REDIRECTS + ") redirects!");
    } else {
      try {
        // 檢查是不是重定向到自身了
        if (lastUrl != null && url.toURI().equals(lastUrl.toURI())) {
          throw new HttpException("In re-direct loop");
        }
      } catch (URISyntaxException e) {
        // Do nothing, this is best effort.
      }
    }

    // connectionFactory默認(rèn)是DefaultHttpUrlConnectionFactory
    // 其build方法就是調(diào)用了url.openConnection()
    urlConnection = connectionFactory.build(url);
    for (Map.Entry<String, String> headerEntry : headers.entrySet()) {
      urlConnection.addRequestProperty(headerEntry.getKey(), headerEntry.getValue());
    }
    urlConnection.setConnectTimeout(timeout);
    urlConnection.setReadTimeout(timeout);
    urlConnection.setUseCaches(false);
    urlConnection.setDoInput(true);

    // 禁止HttpUrlConnection自動(dòng)重定向,重定向功能由本方法自己實(shí)現(xiàn)
    urlConnection.setInstanceFollowRedirects(false);

    // Connect explicitly to avoid errors in decoders if connection fails.
    urlConnection.connect();
    // Set the stream so that it's closed in cleanup to avoid resource leaks. See #2352.
    stream = urlConnection.getInputStream();
    if (isCancelled) {
      return null;
    }
    final int statusCode = urlConnection.getResponseCode();
    if (isHttpOk(statusCode)) {
      // statusCode=2xx,請(qǐng)求成功
      return getStreamForSuccessfulRequest(urlConnection);
    } else if (isHttpRedirect(statusCode)) {
      // statusCode=3xx,需要重定向
      String redirectUrlString = urlConnection.getHeaderField("Location");
      if (TextUtils.isEmpty(redirectUrlString)) {
        throw new HttpException("Received empty or null redirect url");
      }
      URL redirectUrl = new URL(url, redirectUrlString);
      // Closing the stream specifically is required to avoid leaking ResponseBodys in addition
      // to disconnecting the url connection below. See #2352.
      cleanup();
      return loadDataWithRedirects(redirectUrl, redirects + 1, url, headers);
    } else if (statusCode == INVALID_STATUS_CODE) {
      // -1 表示不是HTTP響應(yīng)
      throw new HttpException(statusCode);
    } else {
      throw new HttpException(urlConnection.getResponseMessage(), statusCode);
    }
  }
  
private static boolean isHttpOk(int statusCode) {
  return statusCode / 100 == 2;
}

private static boolean isHttpRedirect(int statusCode) {
  return statusCode / 100 == 3;
}

現(xiàn)在我們已經(jīng)獲得網(wǎng)絡(luò)圖片的InputStream了,該資源會(huì)通過(guò)回調(diào)經(jīng)過(guò)MultiFetcher到達(dá)SourceGenerator中??聪翫ataCallback回調(diào)在SourceGenerator中的實(shí)現(xiàn):

  // SourceGenerator
  @Override
  public void onDataReady(Object data) {
    DiskCacheStrategy diskCacheStrategy = helper.getDiskCacheStrategy();
    if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) {
      dataToCache = data;
      // We might be being called back on someone else's thread. Before doing anything, we should
      // reschedule to get back onto Glide's thread.
      cb.reschedule();
    } else {
      cb.onDataFetcherReady(loadData.sourceKey, data, loadData.fetcher,
          loadData.fetcher.getDataSource(), originalKey);
    }
  }

  @Override
  public void onLoadFailed(@NonNull Exception e) {
    cb.onDataFetcherFailed(originalKey, e, loadData.fetcher, loadData.fetcher.getDataSource());
  }

onDataReady方法會(huì)首先判data能不能緩存,若能緩存則緩存起來(lái),然后調(diào)用DataCacheGenerator進(jìn)行加載緩存;若不能緩存,則直接調(diào)用DecodeJob.onDataFetcherReady方法通知外界data已經(jīng)準(zhǔn)備好了。繼續(xù)跟進(jìn)
DecodeJob.onDataFetcherReady:

  // DecodeJob
  @Override
  public void onDataFetcherReady(Key sourceKey, Object data, DataFetcher<?> fetcher,
      DataSource dataSource, Key attemptedKey) {
    this.currentSourceKey = sourceKey;
    this.currentData = data;
    this.currentFetcher = fetcher;
    this.currentDataSource = dataSource;
    this.currentAttemptingKey = attemptedKey;
    if (Thread.currentThread() != currentThread) {
      runReason = RunReason.DECODE_DATA;
      callback.reschedule(this);
    } else {
      GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData");
      try {
        decodeFromRetrievedData();
      } finally {
        GlideTrace.endSection();
      }
    }
  }

確認(rèn)執(zhí)行線程后調(diào)用decodeFromRetrievedData()方法進(jìn)行解碼:

  // DecodeJob
  private void decodeFromRetrievedData() {
    if (Log.isLoggable(TAG, Log.VERBOSE)) {
      logWithTimeAndKey("Retrieved data", startFetchTime,
          "data: " + currentData
              + ", cache key: " + currentSourceKey
              + ", fetcher: " + currentFetcher);
    }
    Resource<R> resource = null;
    try {
      resource = decodeFromData(currentFetcher, currentData, currentDataSource);
    } catch (GlideException e) {
      e.setLoggingDetails(currentAttemptingKey, currentDataSource);
      throwables.add(e);
    }
    if (resource != null) {
      notifyEncodeAndRelease(resource, currentDataSource);
    } else {
      runGenerators();
    }
  }

先調(diào)用decodeFromData方法進(jìn)行解碼,然后調(diào)用notifyEncodeAndRelease方法進(jìn)行緩存,同時(shí)也會(huì)通知EngineJob資源已經(jīng)準(zhǔn)備好了,先看decodeFromData:

  // DecodeJob
  private <Data> Resource<R> decodeFromData(DataFetcher<?> fetcher, Data data,
      DataSource dataSource) throws GlideException {
    try {
      if (data == null) {
        return null;
      }
      long startTime = LogTime.getLogTime();
      Resource<R> result = decodeFromFetcher(data, dataSource);
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        logWithTimeAndKey("Decoded result " + result, startTime);
      }
      return result;
    } finally {
      fetcher.cleanup();
    }
  }
  
  private <Data> Resource<R> decodeFromFetcher(Data data, DataSource dataSource)
      throws GlideException {
    LoadPath<Data, ?, R> path = decodeHelper.getLoadPath((Class<Data>) data.getClass());
    return runLoadPath(data, dataSource, path);
  }

decodeFromData方法內(nèi)部又會(huì)調(diào)用decodeFromFetcher,在decodeFromFetcher方法中首先會(huì)獲取LoadPath。然后調(diào)用runLoadPath方法解析成資源:

// DecodeJob
private <Data, ResourceType> Resource<R> runLoadPath(Data data, DataSource dataSource,
    LoadPath<Data, ResourceType, R> path) throws GlideException {
  Options options = getOptionsWithHardwareConfig(dataSource);
  DataRewinder<Data> rewinder = glideContext.getRegistry().getRewinder(data);
  try {
    // ResourceType in DecodeCallback below is required for compilation to work with gradle.
    return path.load(
        rewinder, options, width, height, new DecodeCallback<ResourceType>(dataSource));
  } finally {
    rewinder.cleanup();
  }
}

注意runLoadPath方法使用到了DataRewinder,這是一個(gè)將數(shù)據(jù)流里面的指針重新指向開(kāi)頭的類,在調(diào)用ResourceDecoder對(duì)data進(jìn)行編碼時(shí)會(huì)嘗試很多個(gè)編碼器,所以每一次嘗試后都需要重置索引。在path.load(rewinder, options, width, height, new DecodeCallback<ResourceType>(dataSource))這行代碼中,最后傳入了一個(gè)DecodeCallback回調(diào),該類的回調(diào)方法會(huì)回調(diào)給DecodeJob對(duì)應(yīng)的方法:

private final class DecodeCallback<Z> implements DecodePath.DecodeCallback<Z> {

  private final DataSource dataSource;

  @Synthetic
  DecodeCallback(DataSource dataSource) {
    this.dataSource = dataSource;
  }

  @NonNull
  @Override
  public Resource<Z> onResourceDecoded(@NonNull Resource<Z> decoded) {
    return DecodeJob.this.onResourceDecoded(dataSource, decoded);
  }
}

繼續(xù)跟進(jìn)LoadPath.load

  // LoadPath
  public Resource<Transcode> load(DataRewinder<Data> rewinder, @NonNull Options options, int width,
      int height, DecodePath.DecodeCallback<ResourceType> decodeCallback) throws GlideException {
    List<Throwable> throwables = Preconditions.checkNotNull(listPool.acquire());
    try {
      return loadWithExceptionList(rewinder, options, width, height, decodeCallback, throwables);
    } finally {
      listPool.release(throwables);
    }
  }

主要調(diào)用了loadWithExceptionList方法

// LoadPath
private Resource<Transcode> loadWithExceptionList(DataRewinder<Data> rewinder,
      @NonNull Options options,
      int width, int height, DecodePath.DecodeCallback<ResourceType> decodeCallback,
      List<Throwable> exceptions) throws GlideException {
    Resource<Transcode> result = null;
    //noinspection ForLoopReplaceableByForEach to improve perf
    for (int i = 0, size = decodePaths.size(); i < size; i++) {
      DecodePath<Data, ResourceType, Transcode> path = decodePaths.get(i);
      try {
        result = path.decode(rewinder, width, height, options, decodeCallback);
      } catch (GlideException e) {
        exceptions.add(e);
      }
      if (result != null) {
        break;
      }
    }

    if (result == null) {
      throw new GlideException(failureMessage, new ArrayList<>(exceptions));
    }

    return result;
  }

對(duì)于每條DecodePath,都調(diào)用其decode方法,直到有一個(gè)DecodePath可以decode出資源。繼續(xù)跟進(jìn)DecodePath.decode:

  // DecodePath
  public Resource<Transcode> decode(DataRewinder<DataType> rewinder, int width, int height,
      @NonNull Options options, DecodeCallback<ResourceType> callback) throws GlideException {
    // 使用ResourceDecoder List進(jìn)行decode
    Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);
    // 將decoded的資源進(jìn)行transform
    Resource<ResourceType> transformed = callback.onResourceDecoded(decoded);
    // 將transformed的資源進(jìn)行transcode
    return transcoder.transcode(transformed, options);
  }

先看一下DecodePath.decodeResource

  @NonNull
  private Resource<ResourceType> decodeResource(DataRewinder<DataType> rewinder, int width,
      int height, @NonNull Options options) throws GlideException {
    List<Throwable> exceptions = Preconditions.checkNotNull(listPool.acquire());
    try {
      return decodeResourceWithList(rewinder, width, height, options, exceptions);
    } finally {
      listPool.release(exceptions);
    }
  }

繼續(xù)跟進(jìn)DecodePath.decodeResourceWithList

@NonNull
  private Resource<ResourceType> decodeResourceWithList(DataRewinder<DataType> rewinder, int width,
      int height, @NonNull Options options, List<Throwable> exceptions) throws GlideException {
    Resource<ResourceType> result = null;
    
    // decoders只有一條,就是ByteBufferBitmapDecoder
    for (int i = 0, size = decoders.size(); i < size; i++) {
      ResourceDecoder<DataType, ResourceType> decoder = decoders.get(i);
      try {
      
        // rewinder是ByteBufferRewind類型
        // data為ByteBuffer類型
        DataType data = rewinder.rewindAndGet();
        if (decoder.handles(data, options)) {
          // 調(diào)用ByteBuffer.position(0)復(fù)位
          data = rewinder.rewindAndGet();
          // 開(kāi)始解碼
          result = decoder.decode(data, width, height, options);
        }
       
      } catch (IOException | RuntimeException | OutOfMemoryError e) {
        ...
      }

      if (result != null) {
        break;
      }
    }
    ...
    return result;
  }

繼續(xù)跟進(jìn)ByteBufferBitmapDecoder.decode方法

  @Override
  public Resource<Bitmap> decode(@NonNull ByteBuffer source, int width, int height,
      @NonNull Options options)
      throws IOException {
    InputStream is = ByteBufferUtil.toStream(source);
    return downsampler.decode(is, width, height, options);
  }

先將ByteBuffer轉(zhuǎn)換成InputStream,然后在調(diào)用Downsampler.decode方法進(jìn)行解碼。回到DecodePath.decode,解碼后調(diào)用callback.onResourceDecoded(decoded);,DecodeJob中的DecodeCallback實(shí)現(xiàn)了DecodePath.DecodeCallback的onResourceDecoded方法,該方法里面調(diào)用了DecodeJob.onResourceDecoded(dataSource, decoded):

// DecodeJob
<Z> Resource<Z> onResourceDecoded(DataSource dataSource,
      @NonNull Resource<Z> decoded) {

    Class<Z> resourceSubClass = (Class<Z>) decoded.get().getClass();
    Transformation<Z> appliedTransformation = null;
    Resource<Z> transformed = decoded;
    
    // dataSource為DATA_DISK_CACHE,所以滿足條件
    if (dataSource != DataSource.RESOURCE_DISK_CACHE) {
      appliedTransformation = decodeHelper.getTransformation(resourceSubClass);
      transformed = appliedTransformation.transform(glideContext, decoded, width, height);
    }
    
    ...

    final EncodeStrategy encodeStrategy;
    final ResourceEncoder<Z> encoder;
    // Bitmap有注冊(cè)對(duì)應(yīng)的BitmapEncoder,所以是available的
    if (decodeHelper.isResourceEncoderAvailable(transformed)) {
      // encoder就是BitmapEncoder
      encoder = decodeHelper.getResultEncoder(transformed);
      // encodeStrategy為EncodeStrategy.TRANSFORMED
      encodeStrategy = encoder.getEncodeStrategy(options);
    } else {
      encoder = null;
      encodeStrategy = EncodeStrategy.NONE;
    }

    Resource<Z> result = transformed;
    
    ...

    return result;
  }

繼續(xù)回到DecodePath.decode方法中的transcoder.transcode(transformed, options);
這里的transcoder就是BitmapDrawableTranscoder,該方法返回了一個(gè)LazyBitmapDrawableResource。至此,資源已經(jīng)解碼完畢。然后我們繼續(xù)回到 DecodeJob.decodeFromRetrievedData方法中:

// DecodeJob
private void decodeFromRetrievedData() {
    if (Log.isLoggable(TAG, Log.VERBOSE)) {
      logWithTimeAndKey("Retrieved data", startFetchTime,
          "data: " + currentData
              + ", cache key: " + currentSourceKey
              + ", fetcher: " + currentFetcher);
    }
    Resource<R> resource = null;
    try {
      resource = decodeFromData(currentFetcher, currentData, currentDataSource);
    } catch (GlideException e) {
      e.setLoggingDetails(currentAttemptingKey, currentDataSource);
      throwables.add(e);
    }
    if (resource != null) {
      notifyEncodeAndRelease(resource, currentDataSource);
    } else {
      runGenerators();
    }
  }

拿到 resource 之后會(huì)調(diào)用notifyEncodeAndRelease(resource, currentDataSource);,跟進(jìn) DecodeJob.notifyEncodeAndRelease:

// DecodeJob
private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {

    // resource是BitmapResource類型,實(shí)現(xiàn)了Initializable接口
    if (resource instanceof Initializable) {
      // initialize方法調(diào)用了bitmap.prepareToDraw()
      ((Initializable) resource).initialize();
    }

    Resource<R> result = resource;
    ...

    // 通知回調(diào),資源已經(jīng)就緒
    notifyComplete(result, dataSource);

    ...
    
    // 進(jìn)行清理工作
    onEncodeComplete();
  }

notifyComplete方法中該方法內(nèi)部會(huì)調(diào)用callback.onResourceReady(resource, dataSource)將結(jié)果傳遞給回調(diào),這里的回調(diào)是EngineJob:

// EngineJob
  @Override
  public void onResourceReady(Resource<R> resource, DataSource dataSource) {
    synchronized (this) {
      this.resource = resource;
      this.dataSource = dataSource;
    }
    notifyCallbacksOfResult();
  }

這里存儲(chǔ)資源后繼續(xù)調(diào)用EngineJob.notifyCallbacksOfResult

// EngineJob
@Synthetic
  void notifyCallbacksOfResult() {
    ResourceCallbacksAndExecutors copy;
    Key localKey;
    EngineResource<?> localResource;
    synchronized (this) {
      stateVerifier.throwIfRecycled();
      if (isCancelled) {
        resource.recycle();
        release();
        return;
      } else if (cbs.isEmpty()) {
        throw new IllegalStateException("Received a resource without any callbacks to notify");
      } else if (hasResource) {
        throw new IllegalStateException("Already have resource");
      }
      
      // new EngineResource<>(resource, isMemoryCacheable, /*isRecyclable=*/ true)
      engineResource = engineResourceFactory.build(resource, isCacheable);
     
      hasResource = true;
      copy = cbs.copy();
      incrementPendingCallbacks(copy.size() + 1);

      localKey = key;
      localResource = engineResource;
    }

    // listener就是Engine,該方法會(huì)將資源保存到activeResources中
    listener.onEngineJobComplete(this, localKey, localResource);

    // 這里的ResourceCallbackAndExecutor就是之前創(chuàng)建EngineJob和DecodeJob時(shí)并在執(zhí)行DecodeJob之前添加的回調(diào)
    // entry.executor就是Glide.with.load.into中出現(xiàn)的Executors.mainThreadExecutor()
    // entry.cb就是SingleRequest
    for (final ResourceCallbackAndExecutor entry : copy) {
      entry.executor.execute(new CallResourceReady(entry.cb));
    }
    decrementPendingCallbacks();
  }

先來(lái)看下listener.onEngineJobComplete(this, localKey, localResource),listener就是Engine,跟進(jìn)Engine.onEngineJobComplete:

  // Engine
  @Override
  public synchronized void onEngineJobComplete(
      EngineJob<?> engineJob, Key key, EngineResource<?> resource) {
    
    // 設(shè)置資源的回調(diào)為自己,這樣在資源釋放時(shí)會(huì)通知自己的回調(diào)方法
    if (resource != null) {
      resource.setResourceListener(key, this);

      // 將資源放入activeResources中,資源變?yōu)閍ctive狀態(tài)
      if (resource.isCacheable()) {
        activeResources.activate(key, resource);
      }
    }

    // 將engineJob從Jobs中移除
    jobs.removeIfCurrent(key, engineJob);
  }

再回到EngineJob.notifyCallbacksOfResult,看下entry.executor.execute(new CallResourceReady(entry.cb)),entry.executor就是Glide.with.load.into中出現(xiàn)的Executors.mainThreadExecutor(),內(nèi)部使用MainLooper的Handler,在execute Runnable時(shí)使用此Handler post出去,這里entry.cb就是SingleRequest,所以我們要看下CallResourceReady:

  // EngineJob
  private class CallResourceReady implements Runnable {

    private final ResourceCallback cb;

    CallResourceReady(ResourceCallback cb) {
      this.cb = cb;
    }

    @Override
    public void run() {
      synchronized (EngineJob.this) {
        if (cbs.contains(cb)) {
          engineResource.acquire();
          // 調(diào)用callback
          callCallbackOnResourceReady(cb);
          // 移除callback
          removeCallback(cb);
        }
        decrementPendingCallbacks();
      }
    }
  }

跟進(jìn)EngineJob.callCallbackOnResourceReady

  // EngineJob
  @Synthetic
  synchronized void callCallbackOnResourceReady(ResourceCallback cb) {
    try {
      // 調(diào)用SingleRequest.onResourceReady
      cb.onResourceReady(engineResource, dataSource);
    } catch (Throwable t) {
      throw new CallbackException(t);
    }
  }

繼續(xù)跟進(jìn)SingleRequest.onResourceReady

// SingleRequest
@Override
  public synchronized void onResourceReady(Resource<?> resource, DataSource dataSource) {
    stateVerifier.throwIfRecycled();
    loadStatus = null;
    if (resource == null) {
      ...
      onLoadFailed(exception);
      return;
    }

    Object received = resource.get();
    if (received == null || !transcodeClass.isAssignableFrom(received.getClass())) {
      releaseResource(resource);
      ...
      onLoadFailed(exception);
      return;
    }

    ...

    onResourceReady((Resource<R>) resource, (R) received, dataSource);
  }

這里進(jìn)行一些資源的判空處理,然后調(diào)用onResourceReady((Resource<R>) resource, (R) received, dataSource);

// SingleRequest
private synchronized void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {
    // We must call isFirstReadyResource before setting status.
    
    // 由于requestCoordinator為null,所以返回true
    boolean isFirstResource = isFirstReadyResource();
    // 將status狀態(tài)設(shè)置為COMPLETE
    status = Status.COMPLETE;
    this.resource = resource;

    ...

    isCallingCallbacks = true;
    try {
      // 嘗試調(diào)用各個(gè)listener的onResourceReady回調(diào)進(jìn)行處理
      boolean anyListenerHandledUpdatingTarget = false;
      if (requestListeners != null) {
        for (RequestListener<R> listener : requestListeners) {
          anyListenerHandledUpdatingTarget |=
              listener.onResourceReady(result, model, target, dataSource, isFirstResource);
        }
      }
      anyListenerHandledUpdatingTarget |=
          targetListener != null
              && targetListener.onResourceReady(result, model, target, dataSource, isFirstResource);

      // 如果沒(méi)有一個(gè)回調(diào)能夠處理,那么自己處理
      if (!anyListenerHandledUpdatingTarget) {
        Transition<? super R> animation =
            animationFactory.build(dataSource, isFirstResource);
            
        // target為DrawableImageViewTarget
        target.onResourceReady(result, animation);
      }
    } finally {
      isCallingCallbacks = false;
    }

    notifyLoadSuccess();
  }

DrawableImageViewTarget的基類ImageViewTarget實(shí)現(xiàn)了onResourceReady(result, animation)方法:

  // ImageViewTarget
  @Override
  public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {
    // NO_ANIMATION.transition返回false
    if (transition == null || !transition.transition(resource, this)) {
      setResourceInternal(resource);
    } else {
      maybeUpdateAnimatable(resource);
    }
  }
  
  private void setResourceInternal(@Nullable Z resource) {
    // 設(shè)置資源圖片
    setResource(resource);
    // 有動(dòng)畫則執(zhí)行動(dòng)畫
    maybeUpdateAnimatable(resource);
  }
  
  protected abstract void setResource(@Nullable Z resource);

setResource 方法由 DrawableImageViewTarget 實(shí)現(xiàn)

  // DrawableImageViewTarget
  @Override
  protected void setResource(@Nullable Drawable resource) {
    // view 是 ImageView 類型
    view.setImageDrawable(resource);
  }

至此為止,Glide.with(this).load(url).into(imageView)已經(jīng)將網(wǎng)絡(luò)圖片正確展示在ImageView上。

總結(jié)

Glide.with(this).load(url).into(imageView)整個(gè)源碼調(diào)用時(shí)序圖如下:

參考鏈接
https://muyangmin.github.io/glide-docs-cn/
https://blog.yorek.xyz/android/3rd-library/glide2/

最后編輯于
?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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