Glide源碼分析藻雪,這篇就夠了

提示:Glide源碼比較多秘噪,也比較復(fù)雜,多看幾遍就懂了勉耀。加油~~

一般用法:

 Glide.with(getContext())
                    .load(url)
                    .diskCacheStrategy(DiskCacheStrategy.NONE)
                    .placeholder(R.drawable.ic_default)
                    .into(newDrawableImageViewTarget(mAvatarImgView));
        }

一 指煎、with方法

1.1 Glide.with()

with()方法是Glide類中的一組靜態(tài)方法蹋偏,返回RequestManager對象,它有好幾個(gè)方法重載至壤,我們來看一下Glide類中所有with()方法的方法重載:


 @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.getContext()).get(fragment);
  }

 

1.2 Glide.RequestManagerRetriever()

getRetriever()獲取RequestManagerRetriever威始。


  @NonNull
  private static RequestManagerRetriever getRetriever(@Nullable Context context) {

    //必須要有一個(gè)上下文才能加載
    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();
  }
  @NonNull
  public RequestManagerRetriever getRequestManagerRetriever() {
    return requestManagerRetriever;
  }

1.3 Glide.get(context):

 @NonNull
  public static Glide get(@NonNull Context context) {
   ...
        //初始化Glide
          checkAndInitializeGlide(context,annotationGeneratedModule);
   ...
    
    }

    return glide;
  }
  private static void checkAndInitializeGlide(
      @NonNull Context context, @Nullable GeneratedAppGlideModule generatedAppGlideModule) {
  //glide不能初始化兩次
    if (isInitializing) {
      throw new IllegalStateException(
          "You cannot call Glide.get() in registerComponents(),"
              + " use the provided Glide instance instead");
    }
    isInitializing = true;
    initializeGlide(context, generatedAppGlideModule);
    isInitializing = false;
  }

  private static void initializeGlide(@NonNull Context context,@NonNull GlideBuilder builder,@Nullable GeneratedAppGlideModuleannotationGeneratedModule){
 
  ...
  //創(chuàng)建RequestManagerRetriever.RequestManagerFactory
   RequestManagerRetriever.RequestManagerFactory factory =
        annotationGeneratedModule != null
            ? annotationGeneratedModule.getRequestManagerFactory()
            : null;
    builder.setRequestManagerFactory(factory);
  //這個(gè)builder就是GlideBuilder,用來構(gòu)建Glide對象
         Glide glide = builder.build(applicationContext);
  }

1.4 接著看GlideBuilder類中build方法:


  @NonNull
  Glide build(@NonNull Context context) {
  //sourceExecutor是進(jìn)行網(wǎng)絡(luò)請求的執(zhí)行器
    if (sourceExecutor == null) {
      sourceExecutor = GlideExecutor.newSourceExecutor();
    }
    //diskCacheExecutor磁盤緩存執(zhí)行器像街,后面從磁盤獲取緩存數(shù)據(jù)用到
    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);
    }
//構(gòu)建執(zhí)行引擎
    if (engine == null) {
      engine =
          new Engine(
              memoryCache,
              diskCacheFactory,
              diskCacheExecutor,
              sourceExecutor,
              GlideExecutor.newUnlimitedSourceExecutor(),
              animationExecutor,
              isActiveResourceRetentionAllowed);
    }

    if (defaultRequestListeners == null) {
      defaultRequestListeners = Collections.emptyList();
    } else {
      defaultRequestListeners = Collections.unmodifiableList(defaultRequestListeners);
    }
    //構(gòu)建了一個(gè)RequestManagerRetriever對象
    RequestManagerRetriever requestManagerRetriever =
        new RequestManagerRetriever(requestManagerFactory);
        
//構(gòu)建Glide對象黎棠,并將上面初始化時(shí)創(chuàng)建的各種功能類封裝進(jìn)去
    return new Glide(
        context,
        engine,
        memoryCache,
        bitmapPool,
        arrayPool,
        requestManagerRetriever,
        connectivityMonitorFactory,
        logLevel,
        defaultRequestOptionsFactory,
        defaultTransitionOptions,
        defaultRequestListeners,
        isLoggingRequestOriginsEnabled,
        isImageDecoderEnabledForBitmaps);
  }

以上就是初始化Glide、并構(gòu)建Engine對象镰绎、還有各種線程池脓斩、各種緩存執(zhí)行器等

1.5 RequestManagerRetriever.get()

接著上面繼續(xù),通過RequestManagerRetriever的get方法獲取RequestManager對象
通過上下文類型分別走不同的get方法.


  @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 ContextWrap
          && ((ContextWrapper) context).getBaseContext().getApplicationContext() != null) {
        return get(((ContextWrapper) context).getBaseContext());
      }
    }
    return getApplicationManager(context);
  }

  @SuppressWarnings("deprecation")
  @NonNull
  public RequestManager get(@NonNull Activity activity) {
    if (Util.isOnBackgroundThread()) {
    //如果是是在子線程執(zhí)行畴栖,讓走ApplicationContext的get方法随静,也就是說生命周期跟application保持一致。else里面先判斷activity是否destroyed
      return get(activity.getApplicationContext());
    } else {
      assertNotDestroyed(activity);
      android.app.FragmentManager fm = activity.getFragmentManager();
        //fragmentGet方法里面將glide內(nèi)置的一個(gè)不可見的fragment跟當(dāng)前的activity綁定
      return fragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
    }
  }
  

以傳入上下文是Activity為例吗讶,繼續(xù)查看是怎么得到RequestManager的燎猛,factory就是RequestManagerFactory對象

  private RequestManager fragmentGet(
      @NonNull Context context,
      @NonNull android.app.FragmentManager fm,
      @Nullable android.app.Fragment parentHint,
      boolean isParentVisible) {
      //這個(gè)current就是glide自己的fragment,用來綁定生命周期的关翎。
    RequestManagerFragment current = getRequestManagerFragment(fm, parentHint, isParentVisible);
    RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
     
      Glide glide = Glide.get(context);
      requestManager =
     // private final RequestManagerFactory factory;
     //current.getGlideLifecycle()是glide潛入的frgament的生命周期監(jiān)聽類
    
          factory.build(
              glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
      current.setRequestManager(requestManager);
    }
    return requestManager;
  }

RequestManagerFactory是一個(gè)接口,build方法的參數(shù)里面?zhèn)魅肓薒ifecycle對象扛门。這個(gè)Lifecycle是用來監(jiān)聽內(nèi)潛fragment的生命周期的。

  public interface RequestManagerFactory {
    @NonNull
    RequestManager build(
        @NonNull Glide glide,
        @NonNull Lifecycle lifecycle,
        @NonNull RequestManagerTreeNode requestManagerTreeNode,
        @NonNull Context context);
  }

  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);
        }
      };
  1. RequestManagerRetriever類中看似有很多個(gè)get()方法的重載纵寝,什么Context參數(shù),Activity參數(shù)星立,F(xiàn)ragment參數(shù)等等爽茴,實(shí)際上只有兩種情況而已,即傳入Application類型的參數(shù)绰垂,和傳入非Application類型的參數(shù)室奏。

  2. 如果在Glide.with()方法中傳入的是一個(gè)Application對象,它自動(dòng)就是和應(yīng)用程序的生命周期是同步的劲装,如果應(yīng)用程序關(guān)閉的話胧沫,Glide的加載也會(huì)同時(shí)終止。

  3. 如果在Glide.with()方法中傳入非Application參數(shù)占业,那就是會(huì)向當(dāng)前的Activity當(dāng)中添加一個(gè)隱藏的Fragment绒怨,這個(gè)隱藏的Fragment的生命周期就和當(dāng)前Activity的生命周期綁定了。

  4. 如果我們是在非主線程當(dāng)中使用的Glide谦疾,那么不管你是傳入的Activity還是Fragment南蹂,都會(huì)被強(qiáng)制當(dāng)成Application來處理。

  5. 界面不可見或者銷毀的時(shí)候念恍,通過這樣的方法還能避免Glide持有Activity的實(shí)例而發(fā)生內(nèi)存泄漏問題六剥。

小結(jié):

with()方法傳入當(dāng)前環(huán)境晚顷,是為了讓圖片加載保持生命周期同步。并且返回RequestManager對象供load()方法使用疗疟。RequestManager能夠用于管理和啟動(dòng)對Glide的請求该默。還可以控制生命周期事件智能地停止,啟動(dòng)和重新啟動(dòng)請求.


2策彤、load()方法

2.1 RequestManager.load()

因?yàn)間ilde支持很多圖片來源权均。所以load方法也有很多重栽方法。
load()方法是在RequestManager里面锅锨。

//加載Bitmap
 public RequestBuilder<Drawable> load(@Nullable Bitmap bitmap) {
    return asDrawable().load(bitmap);
  }
 //加載Drawable
    @Override
  public RequestBuilder<Drawable> load(@Nullable Drawable drawable) {
    return asDrawable().load(drawable);
  }
  //加載字符串地址
   @Override
  public RequestBuilder<Drawable> load(@Nullable String string) {
    return asDrawable().load(string);
  }
   //加載字uri
 @Override
  public RequestBuilder<Drawable> load(@Nullable Uri uri) {
    return asDrawable().load(uri);
  }
   //加載字File
 @Override
  public RequestBuilder<Drawable> load(@Nullable File file) {
    return asDrawable().load(file);
  }
   //加載字本地圖資源
 @Override
  public RequestBuilder<Drawable> load(@RawRes @DrawableRes @Nullable Integer resourceId) {
    return asDrawable().load(resourceId);
  }
   //加載字url
  @Override
  @Deprecated
  public RequestBuilder<Drawable> load(@Nullable URL url) {
    return asDrawable().load(url);
  }
  //加載字字節(jié)數(shù)組
  @Override
  public RequestBuilder<Drawable> load(@Nullable byte[] model) {
    return asDrawable().load(model);
  }

//我們?nèi)绻恢付愋偷脑掃瓷蓿J(rèn)是Drawable
  public RequestBuilder<Drawable> asDrawable() {
    return as(Drawable.class);
  }
 //如果需要顯示gif時(shí)
  public RequestBuilder<GifDrawable> asGif() {
    return as(GifDrawable.class).apply(DECODE_TYPE_GIF);
  }
   //如果需要顯示Bitmap時(shí)
  public RequestBuilder<Bitmap> asBitmap() {
    return as(Bitmap.class).apply(DECODE_TYPE_BITMAP);
  }
  public <ResourceType> RequestBuilder<ResourceType> as(
      @NonNull Class<ResourceType> resourceClass) {
    return new RequestBuilder<>(glide, this, resourceClass, context);
  }

as asDrawable()返回的就是RequestBuilder對象。
我們以網(wǎng)絡(luò)獲取圖片為例必搞,傳入String必指,看在RequestBuilder類里面的load方法


  @NonNull
  @Override
  @CheckResult
  public RequestBuilder<TranscodeType> load(@Nullable String string) {
    return loadGeneric(string);
  }
 @NonNull
  private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
    this.model = model;
    isModelSet = true;
    return this;
  }

loadGeneric方法返回RequestBuilder本身,mode就是傳入的加載類型恕洲,也就是字符串麻养,將mode賦值給RequestBuilder的成員變量。
isModelSet是后面用來判斷調(diào)用into方法的,必須在into之前調(diào)用load方法姊氓。

2.2 RequestBuilder


public class RequestBuilder<TranscodeType> extends BaseRequestOptions<RequestBuilder<TranscodeType>>{

  protected static final RequestOptions DOWNLOAD_ONLY_OPTIONS =
      new RequestOptions()
          .diskCacheStrategy(DiskCacheStrategy.DATA)
          .priority(Priority.LOW)
          .skipMemoryCache(true);


  protected RequestBuilder(
      @NonNull Glide glide,
      RequestManager requestManager,
      //資源類型技羔,我們以String為例,transcodeClass就是String類泌类;
      Class<TranscodeType> transcodeClass,
      Context context) {
    this.glide = glide;
    this.requestManager = requestManager;
    this.transcodeClass = transcodeClass;
    this.context = context;
    this.transitionOptions = requestManager.getDefaultTransitionOptions(transcodeClass);
    this.glideContext = glide.getGlideContext();

    initRequestListeners(requestManager.getDefaultRequestListeners());
    apply(requestManager.getDefaultRequestOptions());
  }

RequestBuilder繼承自BaseRequestOptions癞谒,BaseRequestOptions里面就是一些需要的配置
比如:設(shè)置是否跳過緩存,是否磁盤緩存刃榨,展位圖等弹砚。我們傳入自己的配置即可。

             Glide.with(getContext())
                    .load(url)
                    .skipMemoryCache(true) 
                    .diskCacheStrategy(DiskCacheStrategy.NONE)
                    .placeholder(R.drawable.ic_default)
                    .into(newDrawableImageViewTarget(mAvatarImgView));
                    

小結(jié)

1枢希、load方法用來傳入加載的圖片資源路徑桌吃。

2、再調(diào)load方法之前需要設(shè)置請求類型是gif或者Bitmap苞轿,不設(shè)置默認(rèn)時(shí)Drawable茅诱。

3、load之后需要設(shè)置請求的一些配置參數(shù)搬卒。是否使用緩存瑟俭,展位圖等。

4秀睛、最終返回的是配置好請求類型的RequestBuilder尔当,用來進(jìn)行下一步into調(diào)用。


3、into()方法

3.1 RequestBuilder.into()

@NonNull
  public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
  //先判斷是否在主線程
    Util.assertMainThread();
    //檢測imageView是否為null
    Preconditions.checkNotNull(view);
    //獲取配置好的RequestOptions椭迎,再配置imageView的縮放類型锐帜。
    BaseRequestOptions<?> requestOptions = this;
    if (!requestOptions.isTransformationSet()
        && requestOptions.isTransformationAllowed()
        && view.getScaleType() != null) {
      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(
        //構(gòu)建Target:DrawableImageViewTarget(view)或者是BitmapImageViewTarget(view)
        //因?yàn)槲覀兡J(rèn)是Drawable,所以transcodeClass是Drawable.class
        glideContext.buildImageViewTarget(view, transcodeClass),
        /*targetListener=*/ null,
        //配置好的請求參數(shù)
        requestOptions,
        //主線程執(zhí)行器畜号,Executors的構(gòu)造方法里面有:Handler handler = new Handler(Looper.getMainLooper());
        Executors.mainThreadExecutor());
  }

看一下GlideContext的buildImageViewTarget方法缴阎,參數(shù)是我們的控件View和最終轉(zhuǎn)碼類型的字節(jié)碼
GlideContext類是在Glide初始化的最后構(gòu)建的,用來全局提供Glide構(gòu)建的配置類對象的简软,比如它的getEngine()方法蛮拔,返回Engine對象。

3.1.1 GlideContext.buildImageViewTarget

  @NonNull
  public <X> ViewTarget<ImageView, X> buildImageViewTarget(
      @NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {
    return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
  }

3.1.2 ImageViewTargetFactory.buildTarget
通過傳入的資源轉(zhuǎn)碼類型去創(chuàng)建不同的Target:
new BitmapImageViewTarget(view)和
new DrawableImageViewTarget(view)痹升;

 */
public class ImageViewTargetFactory {
  
  public <Z> ViewTarget<ImageView, Z> buildTarget(
      @NonNull ImageView view, @NonNull Class<Z> clazz) {
    if (Bitmap.class.equals(clazz)) {
      return (ViewTarget<ImageView, Z>) new BitmapImageViewTarget(view);
    } else if (Drawable.class.isAssignableFrom(clazz)) {
      return (ViewTarget<ImageView, Z>) new DrawableImageViewTarget(view);
    } else {
      throw new IllegalArgumentException(
          "Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
    }
  }
}

3.1.3 DrawableImageViewTarget

看下DrawableImageViewTarget類建炫,有個(gè)setResource()方法,這玩意應(yīng)該就是最后將獲取到的資源圖片顯示到控件的方法了疼蛾。

public class DrawableImageViewTarget extends ImageViewTarget<Drawable> {

  public DrawableImageViewTarget(ImageView view) {
    super(view);
  }

  /** @deprecated Use {@link #waitForLayout()} instead. */
  // Public API.
  @SuppressWarnings({"unused", "deprecation"})
  @Deprecated
  public DrawableImageViewTarget(ImageView view, boolean waitForLayout) {
    super(view, waitForLayout);
  }

  @Override
  protected void setResource(@Nullable Drawable resource) {
    view.setImageDrawable(resource);
  }
}

3.1.4 Executors.mainThreadExecutor()
構(gòu)造器里創(chuàng)建了主線程的handle對象肛跌,再exectue執(zhí)行后,handle.post(command)將數(shù)據(jù)傳遞到主線程

public final class Executors {
  private Executors() {
    // Utility class.
  }

  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);
        }
      };
  private static final Executor DIRECT_EXECUTOR =
      new Executor() {
        @Override
        public void execute(@NonNull Runnable command) {
          command.run();
        }
      };

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

繼續(xù)return的into方法

3.2 RequestBuilder.into()

  private <Y extends Target<TranscodeType>> Y into(
    //在GlideContext中創(chuàng)建的target
      @NonNull Y target,
        //null
      @Nullable RequestListener<TranscodeType> targetListener,
      //requestBuilder配置的參數(shù)
      BaseRequestOptions<?> options,
        //主線程執(zhí)行器
      Executor callbackExecutor) {
      
    Preconditions.checkNotNull(target);
    //isModelSet的作用察郁。
    if (!isModelSet) {
      throw new IllegalArgumentException("You must call #load() before calling #into()");
    }
    //通過我們傳入的參數(shù)調(diào)buildRequest方法衍慎,返回一個(gè)request,callbackExecutor含有綁定主線程的Handler
    Request request = buildRequest(target, targetListener, options, callbackExecutor);
    //在給target設(shè)置request之前,看下這個(gè)target之前有沒有老的request皮钠。
    Request previous = target.getRequest();
    //如果兩個(gè)request等價(jià)稳捆,并且老的request有設(shè)置緩存,并且老request的不為null麦轰,并且不在Running中乔夯,就調(diào)用request的begin()方法,讓他開始加載原朝。并返回這個(gè)target驯嘱。
    if (request.isEquivalentTo(previous)
        && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
     
      if (!Preconditions.checkNotNull(previous).isRunning()) {
    
        previous.begin();
      }
      return target;
    }
    //如果上面判斷不成立。則clear老的request喳坠,將新的request設(shè)置給target。并且執(zhí)行 requestManager.track()方法茂蚓。返回target壕鹉。
    requestManager.clear(target);
    ==target==.setRequest(request);
    requestManager.track(target, request);

    return target;
  }

注意:Request類是個(gè)接口,本身有start聋涨,pause晾浴,clear,isRunning牍白,isComplete脊凰,isEquivalentTo等方法。我們這里最終返回的Request就是后面說的==SingleRequest==對象。

** 3.2.1 說這個(gè)buildRequest方法之前狸涌,解釋一下requestManager.track這個(gè)方法**

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

3.2.2 看下TargetTracker類:

==TargetTracker實(shí)現(xiàn)LifecycleListener接口==切省,里面創(chuàng)建了一個(gè)targets集合。這個(gè)類的作用就是將所有的target添加到集合帕胆,并在生命周期變化時(shí)管理它朝捆。

public final class TargetTracker implements LifecycleListener {
// targets是一個(gè)具有映射關(guān)系的set無序集合。key就是target懒豹。
//WeakHashMap也是一種hashmap芙盘,特點(diǎn)就是它的key是弱鍵,當(dāng)key不使用的時(shí)候可以被回收脸秽。

  private final Set<Target<?>> targets =
      Collections.newSetFromMap(new WeakHashMap<Target<?>, Boolean>());
//追蹤儒老,將target add到集合里面。
  public void track(@NonNull Target<?> target) {
    targets.add(target);
  }

  public void untrack(@NonNull Target<?> target) {
    targets.remove(target);
  }

  @Override
  public void onStart() {
    for (Target<?> target : Util.getSnapshot(targets)) {
      target.onStart();
    }
  }

  @Override
  public void onStop() {
    for (Target<?> target : Util.getSnapshot(targets)) {
      target.onStop();
    }
  }

3.2.3 RequestTracker

在看 RequestTracker.runRequest方法之前记餐,先看下RequestTracker這個(gè)類:
==RequestTracker是個(gè)管理request的工具類==

public class RequestTracker {
    //將所有的request放入到一個(gè)有映射關(guān)系的set集合中驮樊,用來控制reuqest的行為
    private final Set<Request> requests =Collections.newSetFromMap(new WeakHashMap<Request, Boolean>());
    //排隊(duì)等待執(zhí)行的request的集合 
    private final List<Request> pendingRequests = new ArrayList<>();
    //執(zhí)行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);
    }
  }
  //添加request到集合
     @VisibleForTesting
  void addRequest(Request request) {
    requests.add(request);
  }
  //clearAndRemove集合中的request
    public boolean clearAndRemove(@Nullable Request request) {
       ... 
    }
    //暫停request
    public void pauseRequests() {
      ....  
    }
     //暫停所有的request
    public void pauseAllRequests() {
       ...   
    }
    public void resumeRequests() {
      ...  
    }
    public void clearRequests() {
     ...     
    }
    public void restartRequests() {
       ....   
    }
}

3.2.4 再看 ==RequestTracker.runRequest==方法:

  public void runRequest(@NonNull Request request) {
  //將request添加到集合
  //private final Set<Request> requests =
      Collections.newSetFromMap(new WeakHashMap<Request, Boolean>());====
    requests.add(request);
    //如果沒有暫停,執(zhí)行request的begin方法剥扣。這里request就是后面說的SingerRequest對象巩剖。
    if (!isPaused) {
      request.begin();
    } else {
//如果在暫停,執(zhí)行clear方法  :target.removeCallback(this);
      request.clear();
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        Log.v(TAG, "Paused, delaying request");
      }
      // private final List<Request> pendingRequests = new ArrayList<>();
     
      //放入掛起集合里面等待
      pendingRequests.add(request);
    }
  }

具體的執(zhí)行請求邏輯在后面的SingerRequest中钠怯。

** 3.3 繼續(xù)看RequestBuilder.buildRequest方法:**

private Request buildRequest(
     Target<TranscodeType> target,
     @Nullable RequestListener<TranscodeType> targetListener,
     BaseRequestOptions<?> requestOptions,
     Executor callbackExecutor) {
   return buildRequestRecursive(
       /*requestLock=*/ new Object(),
       target,
       targetListener,
       /*parentCoordinator=*/ null,
       transitionOptions,
       requestOptions.getPriority(),
       requestOptions.getOverrideWidth(),
       requestOptions.getOverrideHeight(),
       requestOptions,
       callbackExecutor);
 
private Request buildRequestRecursive(
    Object requestLock,
    Target<TranscodeType> target,
    @Nullable RequestListener<TranscodeType> targetListener,
    @Nullable RequestCoordinator parentCoordinator,
    TransitionOptions<?, ? super TranscodeType> transitionOptions,
    Priority priority,
    int overrideWidth,
    int overrideHeight,
    BaseRequestOptions<?> requestOptions,
    Executor callbackExecutor) {

 
  Request mainRequest =
      buildThumbnailRequestRecursive(
          requestLock,
          target,
          targetListener,
          parentCoordinator,
          transitionOptions,
          priority,
          overrideWidth,
          overrideHeight,
          requestOptions,
          callbackExecutor);



  private Request buildThumbnailRequestRecursive(
      Object requestLock,
      Target<TranscodeType> target,
      RequestListener<TranscodeType> targetListener,
      @Nullable RequestCoordinator parentCoordinator,
      TransitionOptions<?, ? super TranscodeType> transitionOptions,
      Priority priority,
      int overrideWidth,
      int overrideHeight,
      BaseRequestOptions<?> requestOptions,
      Executor callbackExecutor) {
   ...
//這里省去了許多處理縮略圖的代碼佳魔。
  
      return obtainRequest(
          requestLock,
          target,
          targetListener,
          requestOptions,
          parentCoordinator,
          transitionOptions,
          priority,
          overrideWidth,
          overrideHeight,
          callbackExecutor);
    }
  }

3.3.1 以上代碼主要都是在處理縮略圖的。我們看主要的主線邏輯晦炊。最后return了obtainRequest方法鞠鲜。

  private Request obtainRequest(
      Object requestLock,
      Target<TranscodeType> target,
      RequestListener<TranscodeType> targetListener,
      BaseRequestOptions<?> requestOptions,
      RequestCoordinator requestCoordinator,
      TransitionOptions<?, ? super TranscodeType> transitionOptions,
      Priority priority,
      int overrideWidth,
      int overrideHeight,
      Executor callbackExecutor) {
      //這才是重點(diǎn),最后返回的就是這個(gè)SingleRequest對象
    return SingleRequest.obtain(
        context,
        glideContext,
        requestLock,
        model,
        transcodeClass,
        requestOptions,
        overrideWidth,
        overrideHeight,
        priority,
        target,
        targetListener,
        requestListeners,
        requestCoordinator,
        glideContext.getEngine(),
        transitionOptions.getTransitionFactory(),
        callbackExecutor);
  }

obtainRequest()方法來獲取一個(gè)Request對象.obtainRequest()方法有調(diào)用了SingleRequest.obtain方法断国,傳入之前配置好的參數(shù)各種參數(shù)贤姆。這些參數(shù)其實(shí)都是組裝到Request對象中了。

3.3.2 SingleRequest

==再看下SingleRequest類==稳衬,SingleRequest.obtain的之后就是SingleRequest的初始化操作并且參數(shù)賦值霞捡。這個(gè)SingleRequest就是要返回的request。

public final class SingleRequest<R> implements Request, SizeReadyCallback, ResourceCallback {

  private SingleRequest(
      Context context,
      GlideContext glideContext,
      @NonNull Object requestLock,
      @Nullable Object model,
      Class<R> transcodeClass,
      BaseRequestOptions<?> requestOptions,
      int overrideWidth,
      int overrideHeight,
      Priority priority,
      Target<R> target,
      @Nullable RequestListener<R> targetListener,
      @Nullable List<RequestListener<R>> requestListeners,
      RequestCoordinator requestCoordinator,
      Engine engine,
      TransitionFactory<? super R> animationFactory,
      Executor callbackExecutor) {
    this.requestLock = requestLock;
    this.context = context;
    this.glideContext = glideContext;
    this.model = model;
    this.transcodeClass = transcodeClass;
    this.requestOptions = requestOptions;
    this.overrideWidth = overrideWidth;
    this.overrideHeight = overrideHeight;
    this.priority = priority;
    this.target = target;
    this.targetListener = targetListener;
    this.requestListeners = requestListeners;
    this.requestCoordinator = requestCoordinator;
    this.engine = engine;
    this.animationFactory = animationFactory;
    this.callbackExecutor = callbackExecutor;
    status = Status.PENDING;

    if (requestOrigin == null && glideContext.isLoggingRequestOriginsEnabled()) {
      requestOrigin = new RuntimeException("Glide request origin trace");
    }
  }

==RequestTracker的runRequest中回調(diào)用begin方法(3.2.4中):==

  @Override
  public void begin() {
    synchronized (requestLock) {
      assertNotCallingCallbacks();
        //確定對象沒有被回收
      stateVerifier.throwIfRecycled();
      startTime = LogTime.getLogTime();
       // model(url)為空薄疚,回調(diào)加載失敗
      if (model == null) {
        if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
          width = overrideWidth;
          height = overrideHeight;
        }
        
      }

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

      if (status == Status.COMPLETE) {
        onResourceReady(resource, DataSource.MEMORY_CACHE);
        return;
      }

      //初始化狀態(tài)
      status = Status.WAITING_FOR_SIZE;
      if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
       //如果已經(jīng)設(shè)置好width
        onSizeReady(overrideWidth, overrideHeight);
      } else {
       //通過回調(diào)去監(jiān)界面渲染完成時(shí)獲取view的大斜绦拧( ViewTreeObserver observer = view.getViewTreeObserver();)
       //還是會(huì)調(diào)用onSizeReady
        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));
      }
    }
  }

3.3.3 SingleRequest.onSizeReady

SingleRequest.begin()方法是真正的請求入口;確保ImageView大小獲取到后街夭,調(diào)用SingleRequest的onSizeReady()方法砰碴,繼續(xù):

  public void onSizeReady(int width, int height) {
    stateVerifier.throwIfRecycled();
    synchronized (requestLock) {
      if (IS_VERBOSE_LOGGABLE) {
        logV("Got onSizeReady in " + LogTime.getElapsedMillis(startTime));
      }
      //imager的大小還不確定直接return
      if (status != Status.WAITING_FOR_SIZE) {
        return;
      }
      status = Status.RUNNING;

      float sizeMultiplier = requestOptions.getSizeMultiplier();
      this.width = maybeApplySizeMultiplier(width, sizeMultiplier);
      this.height = maybeApplySizeMultiplier(height, sizeMultiplier);

      if (IS_VERBOSE_LOGGABLE) {
        logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime));
      }
      //這里的engine 是在創(chuàng)建Glide的build()方法中 創(chuàng)建的(第一節(jié)1.4),engine封裝了各種Executor板丽,內(nèi)存緩存等
      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);

   
      if (status != Status.RUNNING) {
        loadStatus = null;
      }
    
    }
  }
  

3.4 Engine

繼續(xù)Engine的load方法:
這里開始圖片的請求呈枉,圖片的三級緩存的功能也在這里
這里我們先定義一下三級緩存:

1、弱引用緩存:使用弱引用,來緩存圖片猖辫,圖片被回收后酥泞,會(huì)保存到內(nèi)存緩存中。

2住册、內(nèi)存緩存LruCache:(默認(rèn)是在創(chuàng)建Glide的時(shí)候創(chuàng)建的婶博,也可自定義), 如果弱引用緩存找不到圖片荧飞,就從內(nèi)存緩存中查找凡人,找到圖片后,刪除內(nèi)存緩存(防止因Lru的策略叹阔,圖片正在使用挠轴,但是被回收掉的問題)。

3耳幢、磁盤緩存 :上面兩級緩存都沒有圖片岸晦,如果在磁盤緩存中找到,就把圖片加載后睛藻,放到弱引用緩存中启上。磁盤緩存數(shù)據(jù)的種類有兩種,一種是緩存源數(shù)據(jù)店印,這種數(shù)據(jù)需要經(jīng)過解析才能得到圖片冈在。一種是圖片數(shù)據(jù),直接加載進(jìn)來就可以用的按摘“可以通過diskCacheStrategyOf 來自由選擇如何緩存

 public <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;
    
//生成緩存key,以后就根據(jù)這個(gè)key炫贤,在緩存中查找

    EngineKey key =
        keyFactory.buildKey(
            model,
            signature,
            width,
            height,
            transformations,
            resourceClass,
            transcodeClass,
            options);
            
//從內(nèi)存里面找是否有目標(biāo)圖片(包括弱應(yīng)用緩存和內(nèi)存緩存)

    EngineResource<?> memoryResource;
    synchronized (this) {
      memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);
      
//如果內(nèi)存里面沒有溅固,進(jìn)入waitForExistingOrStartNewJob方法:
      if (memoryResource == null) {
        return waitForExistingOrStartNewJob(
            glideContext,
            model,
            signature,
            width,
            height,
            resourceClass,
            transcodeClass,
            priority,
            diskCacheStrategy,
            transformations,
            isTransformationRequired,
            isScaleOnlyOrNoTransform,
            options,
            isMemoryCacheable,
            useUnlimitedSourceExecutorPool,
            useAnimationPool,
            onlyRetrieveFromCache,
            cb,
            callbackExecutor,
            key,
            startTime);
      }
    }
    //如果內(nèi)存中能找到,則直接回調(diào)出去
    cb.onResourceReady(memoryResource, DataSource.MEMORY_CACHE);
    return null;

3.4.1

==內(nèi)存中找到的話兰珍,將數(shù)據(jù)回調(diào)到SingleReuest的onResourceReady方法侍郭,最最終通過target將展示圖片到控件。==

  @GuardedBy("requestLock")
  private void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {
    // We must call isFirstReadyResource before setting status.
    boolean isFirstResource = isFirstReadyResource();
    status = Status.COMPLETE;
    this.resource = resource;
...
      if (!anyListenerHandledUpdatingTarget) {
        Transition<? super R> animation = animationFactory.build(dataSource, isFirstResource);
        
//在這里掠河,通過我們之前創(chuàng)建的DrawableImageViewTarget励幼,他繼承自ImageViewTarget,ImageViewTarget有個(gè)抽象方法就是onResourceReady()口柳,最終將將圖片顯示到控件上。
        target.onResourceReady(result, animation);
      }
    } finally {
      isCallingCallbacks = false;
    }

    notifyLoadSuccess();
  }

3.5 從內(nèi)存里面找

  @Nullable
  private EngineResource<?> loadFromMemory(
      EngineKey key, boolean isMemoryCacheable, long startTime) {
    if (!isMemoryCacheable) {
      return null;
    }
 //檢查是弱引用緩存中否有目標(biāo)圖片
    EngineResource<?> active = loadFromActiveResources(key);
    if (active != null) {
      if (VERBOSE_IS_LOGGABLE) {
        logWithTimeAndKey("Loaded resource from active resources", startTime, key);
      }
      return active;
    }
//檢查內(nèi)存的緩存 是否有目標(biāo)圖片
    EngineResource<?> cached = loadFromCache(key);
    if (cached != null) {
      if (VERBOSE_IS_LOGGABLE) {
        logWithTimeAndKey("Loaded resource from cache", startTime, key);
      }
      return cached;
    }

    return null;
  }

3.5.1 Engine.loadFromActiveResources()

 @Nullable
  private EngineResource<?> loadFromActiveResources(Key key) {
  //activeResources獲取弱應(yīng)用緩存
    EngineResource<?> active = activeResources.get(key);
    if (active != null) {
      active.acquire();
    }

    return active;
  }

3.5.2 ActiveResources 弱引用緩存

class ActiveResources {
//這個(gè)map就是ActiveResources里面用來保存弱應(yīng)用緩存的
Map<Key, ResourceWeakReference> activeEngineResources = new HashMap<>();

 @Nullable
 synchronized EngineResource<?> get(Key key) {
  
    ResourceWeakReference activeRef = activeEngineResources.get(key);
    if (activeRef == null) {
      return null;
    }
//找到弱應(yīng)用對象有滑,get到EngineResource返回
    EngineResource<?> active = activeRef.get();
    if (active == null) {
      cleanupActiveReference(activeRef);
    }
    return active;
  }
  
  
//ResourceWeakReference是ActiveResources的內(nèi)部類跃闹,繼承WeakReference
static final class ResourceWeakReference extends WeakReference<EngineResource<?>> {
    final Key key;//緩存key
    final boolean isCacheable;
    Resource<?> resource;//緩存resource
}


 

ActiveResources是保存活動(dòng)資源的一個(gè)類,它里面有個(gè)內(nèi)部類ResourceWeakReference,這個(gè)ResourceWeakReference繼承WeakReference望艺。
這個(gè)ActiveResources里面有一個(gè)value是ResourceWeakReference類型的map苛秕,它主要保存的就是活動(dòng)的資源,我們叫他弱應(yīng)用緩存找默。緩存是先從弱應(yīng)用緩存中查找艇劫,沒找到再去內(nèi)存緩存中查找。

再看下這個(gè)弱應(yīng)用緩存是什么時(shí)候存進(jìn)去的惩激?

//1店煞、弱應(yīng)用緩存沒找到,就會(huì)去內(nèi)存緩存找风钻,內(nèi)存緩存找到后保存到弱應(yīng)用緩存
 private EngineResource<?> loadFromCache(Key key) {
    EngineResource<?> cached = getEngineResourceFromCache(key);
    if (cached != null) {
      cached.acquire();
      //這個(gè)方法就是往弱應(yīng)用緩存map中存數(shù)據(jù)
      activeResources.activate(key, cached);
    }
    return cached;
  }
  
  
  //2顷蟀、當(dāng)內(nèi)存緩存中都沒有找到,那就去磁盤中找骡技,在沒有的就去網(wǎng)絡(luò)獲取鸣个,這時(shí)候獲取到資源并且展示完成后再存到弱應(yīng)用緩存中。
  
  @Override
  public synchronized void onEngineJobComplete(
      EngineJob<?> engineJob, Key key, EngineResource<?> resource) {
    // A null resource indicates that the load failed, usually due to an exception.
    if (resource != null && resource.isMemoryCacheable()) {
      activeResources.activate(key, resource);
    }

    jobs.removeIfCurrent(key, engineJob);
  }

3.6 如果緩存里面沒有布朦,則走下面方法囤萤,從磁盤或者網(wǎng)絡(luò)獲取

//執(zhí)行一個(gè)新的job
 private <R> LoadStatus waitForExistingOrStartNewJob(
    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,
    EngineKey key,
    long startTime) {
//在弱引用和內(nèi)存緩存中,都沒有找到圖片是趴,就執(zhí)行任務(wù)涛舍。
//這個(gè)任務(wù),會(huì)現(xiàn)在磁盤緩存中查找右遭,因?yàn)榇疟P讀取耗時(shí)較大做盅,所以放在任務(wù)線程中
  EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
  //如果current不等于null,說明這個(gè)engineJob已經(jīng)在執(zhí)行了窘哈,不用再次構(gòu)建
  if (current != null) {
    current.addCallback(cb, callbackExecutor);
    if (VERBOSE_IS_LOGGABLE) {
      logWithTimeAndKey("Added to existing load", startTime, key);
    }
    return new LoadStatus(cb, current);
  }
//創(chuàng)建一個(gè)新的engineJob對象吹榴,它里面有很多Executor,用來加載異步圖片
  EngineJob<R> engineJob =
      engineJobFactory.build(
          key,
          isMemoryCacheable,
          useUnlimitedSourceExecutorPool,
          useAnimationPool,
          onlyRetrieveFromCache);
//創(chuàng)建一個(gè)解碼工作的decodeJob滚婉,用于解碼圖片的
  DecodeJob<R> decodeJob =
      decodeJobFactory.build(
          glideContext,
          model,
          key,
          signature,
          width,
          height,
          resourceClass,
          transcodeClass,
          priority,
          diskCacheStrategy,
          transformations,
          isTransformationRequired,
          isScaleOnlyOrNoTransform,
          onlyRetrieveFromCache,
          options,
          engineJob);
// 放在Jobs內(nèi)部維護(hù)的存放任務(wù)的HashMap中(3.6.1)图筹,
  jobs.put(key, engineJob);
// 注冊ResourceCallback接口,就是在成功獲取圖片后让腹,需要顯示到ImageView 上的回調(diào)远剩,這個(gè)接口回調(diào)到SingleRequest 中
  engineJob.addCallback(cb, callbackExecutor);
   //開始執(zhí)行
  engineJob.start(decodeJob);

  if (VERBOSE_IS_LOGGABLE) {
    logWithTimeAndKey("Started new load", startTime, key);
  }
  return new LoadStatus(cb, engineJob);
}

3.6.1 Jobs

Jobs里面維護(hù)了兩個(gè)map,一個(gè)新job骇窍,一個(gè)緩存job瓜晤。

final class Jobs {
  private final Map<Key, EngineJob<?>> jobs = new HashMap<>();
  private final Map<Key, EngineJob<?>> onlyCacheJobs = new HashMap<>();

  @VisibleForTesting
  Map<Key, EngineJob<?>> getAll() {
    return Collections.unmodifiableMap(jobs);
  }

  EngineJob<?> get(Key key, boolean onlyRetrieveFromCache) {
    return getJobMap(onlyRetrieveFromCache).get(key);
  }

  void put(Key key, EngineJob<?> job) {
    getJobMap(job.onlyRetrieveFromCache()).put(key, job);
  }

  void removeIfCurrent(Key key, EngineJob<?> expected) {
    Map<Key, EngineJob<?>> jobMap = getJobMap(expected.onlyRetrieveFromCache());
    if (expected.equals(jobMap.get(key))) {
      jobMap.remove(key);
    }
  }

  private Map<Key, EngineJob<?>> getJobMap(boolean onlyRetrieveFromCache) {
    return onlyRetrieveFromCache ? onlyCacheJobs : jobs;
  }
}

3.7 繼續(xù)EngineJob中的start方法

 public synchronized void start(DecodeJob<R> decodeJob) {
    this.decodeJob = decodeJob;
    //若能從磁盤緩存獲取數(shù)據(jù),就使用diskCacheExecutor腹纳,否則在根據(jù)其他的條件判斷使用哪個(gè)Executor
    //ture:有緩存痢掠,則使用磁盤緩存線程池驱犹。否則返回?cái)?shù)據(jù)源線程池;
    GlideExecutor executor =
        decodeJob.willDecodeFromCache() ? diskCacheExecutor : getActiveSourceExecutor();
        //執(zhí)行decodeJob的run方法
    executor.execute(decodeJob);
  }

通過上面start()方法知道是去磁盤取還是網(wǎng)絡(luò)獲取足画,對應(yīng)執(zhí)行器再去執(zhí)行這個(gè)decodeJob雄驹。

3.8 DecodeJob

這個(gè)類負(fù)責(zé)從磁盤或數(shù)據(jù)源解碼資源,并應(yīng)用轉(zhuǎn)換和轉(zhuǎn)碼淹辞。

在看下DecodeJob的willDecodeFromCache方法:

  boolean willDecodeFromCache() {
    Stage firstStage = getNextStage(Stage.INITIALIZE);
    //如果此作業(yè)將嘗試從磁盤緩存解碼資源医舆,則返回 true,如果它始終從源解碼象缀,則返回 false蔬将。
    return firstStage == Stage.RESOURCE_CACHE || firstStage == Stage.DATA_CACHE;
  }

3.8.1 獲取下一個(gè)階段從哪里獲取數(shù)據(jù)

 private Stage getNextStage(Stage current) {
    switch (current) {
    //若配置的緩存策略允許從磁盤緩存的資源中讀取數(shù)據(jù),則返回Stage.RESOURCE_CACHE
      case INITIALIZE:
        return diskCacheStrategy.decodeCachedResource()
            ? Stage.RESOURCE_CACHE
            : getNextStage(Stage.RESOURCE_CACHE);
     //若配置的緩存策略允許從磁盤緩存的源數(shù)據(jù)緩存讀取數(shù)據(jù)攻冷,則返回Stage.DATA_CACHE
      case RESOURCE_CACHE:
        return diskCacheStrategy.decodeCachedData()
            ? Stage.DATA_CACHE
            : getNextStage(Stage.DATA_CACHE);
     //若只能允許從緩存中讀取數(shù)據(jù)娃胆,則直接FINISH,否則返回Stage.SOURCE,表示加載新的資源
      case DATA_CACHE:
        // Skip loading from source if the user opted to only retrieve the resource from cache.
        return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;
      case SOURCE:
      case FINISHED:
        return Stage.FINISHED;
      default:
        throw new IllegalArgumentException("Unrecognized stage: " + current);
    }
  }

注意:磁盤緩存了兩種資源等曼,一種是數(shù)據(jù)源緩存里烦,一種是磁盤的資源緩存

3.8.2 DecodeJob.run()

public void run() {
    
    GlideTrace.beginSectionFormat("DecodeJob#run(model=%s)", model);
 
    DataFetcher<?> localFetcher = currentFetcher;
    try {
      if (isCancelled) {
        notifyFailed();
        return;
      }
      
      //主要看這:
      runWrapped();
    } catch (CallbackException e) {
   
    } finally {
    
      if (localFetcher != null) {
        localFetcher.cleanup();
      }
      GlideTrace.endSection();
    }
  }

3.8.3 DecodeJob.runWrapped():

  private void runWrapped() {
    switch (runReason) {
    
      case INITIALIZE:
        //獲取下一階段的狀態(tài)
        stage = getNextStage(Stage.INITIALIZE);
         //根據(jù)下一階段狀態(tài),判斷具體有哪個(gè)類執(zhí)行
        currentGenerator = getNextGenerator();
        runGenerators();
        break;
      case SWITCH_TO_SOURCE_SERVICE:
        runGenerators();
        break;
      case DECODE_DATA:
        decodeFromRetrievedData();
        break;
      default:
        throw new IllegalStateException("Unrecognized run reason: " + runReason);
    }
  }

首先從磁盤中去數(shù)據(jù)禁谦。如果磁盤的資源緩存或者磁盤的數(shù)據(jù)源緩存任意一個(gè)沒有取到緩存胁黑,則就去網(wǎng)絡(luò)請求數(shù)據(jù)。
該類繼承了DataFetcherGenerator州泊, 這是一個(gè)數(shù)據(jù)獲取生成器丧蘸。

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

這三個(gè)數(shù)據(jù)抓取執(zhí)行器分別是:磁盤資源緩存執(zhí)行器、磁盤數(shù)據(jù)源執(zhí)行器遥皂、網(wǎng)絡(luò)元數(shù)據(jù)執(zhí)行器力喷;通過這個(gè)stage去選擇哪一個(gè)執(zhí)行器。

3.8.4 DecodeJob.runGenerators()

  private void runGenerators() {
    currentThread = Thread.currentThread();
    startFetchTime = LogTime.getLogTime();
    boolean isStarted = false;
     //判斷邏輯主要看startNext方法演训,這個(gè)方法回去執(zhí)行不同執(zhí)行器的startNext方法弟孟。
    // 返回值是個(gè)布爾值,如果返回true样悟,說明剛才的執(zhí)行器獲取到了緩存拂募,然后去解碼,回調(diào)出去窟她,如果返回false陈症,則執(zhí)行Stage.SOURCE的邏輯,走reschedule()方法
    while (!isCancelled&& currentGenerator != null && !(isStarted = currentGenerator.startNext())) {
      stage = getNextStage(stage);
      currentGenerator = getNextGenerator();

      if (stage == Stage.SOURCE) {
        reschedule();
        return;
      }
    }

    if ((stage == Stage.FINISHED || isCancelled) && !isStarted) {
      notifyFailed();
    }

  }
 @Override
  public void reschedule() {
  //我們想從磁盤緩存服務(wù)切換到源執(zhí)行器震糖。
    runReason = RunReason.SWITCH_TO_SOURCE_SERVICE;
    callback.reschedule(this);
  }
 runReason改變之后录肯,reschedule方法執(zhí)行的就是網(wǎng)絡(luò)獲取執(zhí)行器的邏輯了,

3.8.5 獲取網(wǎng)絡(luò)圖片

所以執(zhí)行SourceGenerator.startNext方法:

  @Override
  public boolean startNext() {
   ...

    loadData = null;
    boolean started = false;
    while (!started && hasNextModelLoader()) {
     //從DecodeHelper的數(shù)據(jù)加載集合中, 獲取一個(gè)數(shù)據(jù)加載器 ModelLoader
     //這些ModelLoader 包括默認(rèn)的和自定義的
      // 這里的符合條件就是判斷在load()傳入的對象類型,是否可以被ModelLoader所處理
           
      loadData = helper.getLoadData().get(loadDataListIndex++);
      if (loadData != null
          && (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
              || helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
        started = true;
        startNextLoad(loadData);
      }
    }
    return started;
  }

3.8.6 DecodeHelp獲取loadData傳入startNextLoad方法


  List<LoadData<?>> getLoadData() {
    if (!isLoadDataSet) {
      isLoadDataSet = true;
      loadData.clear();
       //從Glide注冊的register中獲取modelLoaders
      List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model);
         //遍歷modelLoaders
      for (int i = 0, size = modelLoaders.size(); i < size; i++) {
      //此時(shí)的model為url的string格式吊说,返回該其中一個(gè)實(shí)現(xiàn)類為StringLoader 
        ModelLoader<Object, ?> modelLoader = modelLoaders.get(i);
         //通過函數(shù)buildLoadData 來創(chuàng)建LoadData
        LoadData<?> current = modelLoader.buildLoadData(model, width, height, options);
        if (current != null) {
          loadData.add(current);
        }
      }
    }
    return loadData;
  }

3.8.7 startNextLoad()

繼續(xù)查看 startNextLoad()方法接著通過LoadData對象內(nèi)部的 fetcher 嘁信,來進(jìn)行實(shí)際的請求操作(例如發(fā)起網(wǎng)絡(luò)請求)

private void startNextLoad(final LoadData<?> toStart) {
   loadData.fetcher.loadData(
       helper.getPriority(),
       new DataCallback<Object>() {
         @Override
         public void onDataReady(@Nullable Object data) {
           if (isCurrentRequest(toStart)) {
             onDataReadyInternal(toStart, data);
           }
         }

         @Override
         public void onLoadFailed(@NonNull Exception e) {
           if (isCurrentRequest(toStart)) {
             onLoadFailedInternal(toStart, e);
           }
         }
       });
 }

** 3.8.8 **

接著上面 loadData.fetcher.loadData邏輯于样,他是最終獲取資源的,比如網(wǎng)絡(luò)請求數(shù)據(jù),fetcher是HttpUrlFetcher:

 @Override
public void loadData(
    @NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) {
  long startTime = LogTime.getLogTime();
  try {
  //網(wǎng)絡(luò)請求數(shù)據(jù)
    InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
    //數(shù)據(jù)獲取成功的回調(diào)
    callback.onDataReady(result);
  } catch (IOException e) {

    callback.onLoadFailed(e);
  } finally {
  
  }
}

** 3.8.9 **

執(zhí)行網(wǎng)絡(luò)請求返回?cái)?shù)據(jù)流

 private InputStream loadDataWithRedirects(
      URL url, int redirects, URL lastUrl, Map<String, String> headers) throws IOException {
    if (redirects >= MAXIMUM_REDIRECTS) {
      throw new HttpException("Too many (> " + MAXIMUM_REDIRECTS + ") redirects!");
    } else {
      // Comparing the URLs using .equals performs additional network I/O and is generally broken.
      // See http://michaelscharf.blogspot.com/2006/11/javaneturlequals-and-hashcode-make.html.
      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.
      }
    }

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

    // Stop the urlConnection instance of HttpUrlConnection from following redirects so that
    // redirects will be handled by recursive calls to this method, loadDataWithRedirects.
    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)) {
      return getStreamForSuccessfulRequest(urlConnection);
    } else if (isHttpRedirect(statusCode)) {
      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) {
      throw new HttpException(statusCode);
    } else {
      throw new HttpException(urlConnection.getResponseMessage(), statusCode);
    }
  }

** 3.8.10 **

請求數(shù)據(jù)成功后潘靖, callback.onDataReady(result)在SourceGenerator的startNextLoad里面(3.8.7)接收回調(diào)數(shù)據(jù),

private void startNextLoad(final LoadData<?> toStart) {
    loadData.fetcher.loadData(
        helper.getPriority(),
        new DataCallback<Object>() {
          @Override
          public void onDataReady(@Nullable Object data) {
            if (isCurrentRequest(toStart)) {
              onDataReadyInternal(toStart, data);
            }
          }

          @Override
          public void onLoadFailed(@NonNull Exception e) {
            if (isCurrentRequest(toStart)) {
              onLoadFailedInternal(toStart, e);
            }
          }
        });
  }

**3.9 **

這時(shí)候數(shù)據(jù)已經(jīng)請求到了蚤蔓,執(zhí)行onDataReadyInternal方法卦溢,參數(shù)有l(wèi)oadDate和請求到的數(shù)據(jù)

  @SuppressWarnings("WeakerAccess")
  @Synthetic
  void onDataReadyInternal(LoadData<?> loadData, Object data) {
    DiskCacheStrategy diskCacheStrategy = helper.getDiskCacheStrategy();
    //如果該數(shù)據(jù)類型,有啟用磁盤緩存秀又,就把值賦給dataToCache
    if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) {
      dataToCache = data;
      //調(diào)用DecodeJob的reschedule单寂,用線程池執(zhí)行任務(wù),實(shí)際上就是再次調(diào)用SourceGenerator的startNext
      cb.reschedule();
    } else {
     // 繼續(xù)回調(diào)FetcherReadyCallback的onDataFetcherReady方法吐辙,將data回調(diào)出去
      cb.onDataFetcherReady(
          loadData.sourceKey,
          data,
          loadData.fetcher,
          loadData.fetcher.getDataSource(),
          originalKey);
    }
  }

3.9.1 解析數(shù)據(jù)

這個(gè)回調(diào)方法走的是DecodeJob.onDataFetcherReady(),DecodeJob類實(shí)現(xiàn)了FetcherReadyCallback接口宣决。
然后解析數(shù)據(jù)

 @Override
  public void reschedule() {
    runReason = RunReason.SWITCH_TO_SOURCE_SERVICE;
    callback.reschedule(this);
  }

  @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 {
      //解析獲取到的數(shù)據(jù)
        decodeFromRetrievedData();
      } finally {
        GlideTrace.endSection();
      }
    }
  }

3.9.2

DecodeJob.decodeFromRetrievedData
==解析得到資源==

  private void decodeFromRetrievedData() {

    Resource<R> resource = null;
    try {
     // 從數(shù)據(jù)中解碼得到資源
      resource = decodeFromData(currentFetcher, currentData, currentDataSource);
    } catch (GlideException e) {
   ...
    }
     // 最終得到的Resource<Drawable>對象,
    if (resource != null) {
      notifyEncodeAndRelease(resource, currentDataSource);
    } else {
      runGenerators();
    }
  }

至此:得到了網(wǎng)絡(luò)請求的數(shù)據(jù)昏苏,并解析后得到了資源

3.9.3

看下怎么解析數(shù)據(jù)的

  private <Data> Resource<R> decodeFromData(
      DataFetcher<?> fetcher, Data data, DataSource dataSource) throws GlideException {
    try {
      if (data == null) {
        return null;
      }
      long startTime = LogTime.getLogTime();
       //繼續(xù)解析數(shù)據(jù)
      Resource<R> result = decodeFromFetcher(data, dataSource);
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        logWithTimeAndKey("Decoded result " + result, startTime);
      }
      return result;
    } finally {
      fetcher.cleanup();
    }
  }

這里的data 是一個(gè)泛型尊沸,本例中是 Stream 流,從http請求獲取到的

    private <Data> Resource<R> decodeFromFetcher(Data data, DataSource dataSource){
  
    
    LoadPath<Data, ?, R> path = decodeHelper.getLoadPath((Class<Data>) data.getClass());
    
    //通過解析器來解析數(shù)據(jù)
    return runLoadPath(data, dataSource, path);
  }
  

上面代碼看出:
1贤惯、獲取一個(gè)LoadPath洼专,它是根據(jù)數(shù)據(jù)類型(這里是stream),ResourceDecoder(資源解碼)孵构,transcoder(資源轉(zhuǎn)碼)

2屁商、從這些參數(shù)可以看出,最終把數(shù)據(jù)流轉(zhuǎn)為Bitmap 或Drawable 颈墅,就是在LoadPath中進(jìn)行的蜡镶,這里是指DecodePath

  private <Data, ResourceType> Resource<R> runLoadPath(
      Data data, DataSource dataSource, LoadPath<Data, ResourceType, R> path)
      throws GlideException {
    Options options = getOptionsWithHardwareConfig(dataSource);
    
    //此時(shí)的data為InputStream對象,故rewinder為InputStreamRewinder對象
    DataRewinder<Data> rewinder = glideContext.getRegistry().getRewinder(data);
    try {
    
      //執(zhí)行LoadPath 的load 恤筛,進(jìn)行解碼官还,轉(zhuǎn)換操作
      return path.load(
          rewinder, options, width, height, new DecodeCallback<ResourceType>(dataSource));
    } finally {
      rewinder.cleanup();
    }
  }

3.9.4
LoadPath.load() 解析數(shù)據(jù)


  public Resource<Transcode> load(
      {
    ...參數(shù)省略...
      return loadWithExceptionList(rewinder, options, width, height, decodeCallback, throwables);
    } finally {
      listPool.release(throwables);
    }
  }

重點(diǎn)在下面方法:正真的解碼


  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;
      //遍歷DecodePath集合
    for (int i = 0, size = decodePaths.size(); i < size; i++) {
      DecodePath<Data, ResourceType, Transcode> path = decodePaths.get(i);
      try {
        //重點(diǎn):調(diào)用DecodePath.decode真正進(jìn)行數(shù)據(jù)解析
        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;
  }

解碼邏輯:

  public Resource<Transcode> decode(
      DataRewinder<DataType> rewinder,
      int width,
      int height,
      @NonNull Options options,
      DecodeCallback<ResourceType> callback)
      throws GlideException {
     //獲取到Resource<BItmap>對象  
    Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);
      // 這個(gè)方法是回調(diào)到Decodejob.onResourceDecoded ,作用是調(diào)用RequestOptions中的Transform處理圖片,然后將ResourceCache的Key和Encode準(zhǔn)備好(放在變量 deferEncoderManager中)叹俏,最后將這個(gè)源數(shù)據(jù)進(jìn)行寫入磁盤緩存妻枕。
//這就是磁盤的源數(shù)據(jù)緩存。
    Resource<ResourceType> transformed = callback.onResourceDecoded(decoded);
     //進(jìn)行數(shù)據(jù)類型的轉(zhuǎn)換
    return transcoder.transcode(transformed, options);
  }

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

3.9.5

繼續(xù)decodeResourceWithList方法:decoder是一個(gè)ResourceDecoder接口(資源解碼器)粘驰,根據(jù)不同的DataType和ResourceType它會(huì)有不同的實(shí)現(xiàn)類屡谐,這里的實(shí)現(xiàn)類是ByteBufferBitmapDecoder

  private Resource<ResourceType> decodeResourceWithList(
        DataRewinder<DataType> rewinder,
      int width,
      int height,
      @NonNull Options options,
      List<Throwable> exceptions)
      throws GlideException {
    Resource<ResourceType> result = null;
    //noinspection ForLoopReplaceableByForEach to improve perf
    for (int i = 0, size = decoders.size(); i < size; i++) {
      ResourceDecoder<DataType, ResourceType> decoder = decoders.get(i);
      try {
        DataType data = rewinder.rewindAndGet();
        if (decoder.handles(data, options)) {
          data = rewinder.rewindAndGet();
            //根據(jù)DataType和ResourceType的類型分發(fā)給不同的解碼器Decoder     
          result = decoder.decode(data, width, height, options);
        }
    
      } catch (IOException | RuntimeException | 
      }

    return result;
  }

3.9.6
ByteBufferBitmapDecoder的decode方法,
里面有個(gè)downsampler類,downsampler主要是對流進(jìn)行解碼蝌数,旋轉(zhuǎn)愕掏,壓縮,圓角等處理

public class ByteBufferBitmapDecoder implements ResourceDecoder<ByteBuffer, Bitmap> {
  private final Downsampler downsampler;

  public ByteBufferBitmapDecoder(Downsampler downsampler) {
    this.downsampler = downsampler;
  }

  @Override
  public boolean handles(@NonNull ByteBuffer source, @NonNull Options options) {
    return downsampler.handles(source);
  }

  @Override
  public Resource<Bitmap> decode(
      @NonNull ByteBuffer source, int width, int height, @NonNull Options options)
      throws IOException {
    InputStream is = ByteBufferUtil.toStream(source);
    //downsampler主要是對流進(jìn)行解碼顶伞,旋轉(zhuǎn)饵撑,壓縮剑梳,圓角等處理
    return downsampler.decode(is, width, height, options);
  }
}

3.9.7
繼續(xù)DownSampler中的decode方法,省去多次跳轉(zhuǎn):

 private Resource<Bitmap> decode(
      ImageReader imageReader,
      int requestedWidth,
      int requestedHeight,
      Options options,
      DecodeCallbacks callbacks)
      throws IOException {
    byte[] bytesForOptions = byteArrayPool.get(ArrayPool.STANDARD_BUFFER_SIZE_BYTES, byte[].class);
    BitmapFactory.Options bitmapFactoryOptions = getDefaultOptions();
    bitmapFactoryOptions.inTempStorage = bytesForOptions;

    DecodeFormat decodeFormat = options.get(DECODE_FORMAT);
    PreferredColorSpace preferredColorSpace = options.get(PREFERRED_COLOR_SPACE);
    DownsampleStrategy downsampleStrategy = options.get(DownsampleStrategy.OPTION);
    boolean fixBitmapToRequestedDimensions = options.get(FIX_BITMAP_SIZE_TO_REQUESTED_DIMENSIONS);
    boolean isHardwareConfigAllowed =
        options.get(ALLOW_HARDWARE_CONFIG) != null && options.get(ALLOW_HARDWARE_CONFIG);

    try {
    //得到解析后的bitmap
      Bitmap result =
          decodeFromWrappedStreams(
              imageReader,
              bitmapFactoryOptions,
              downsampleStrategy,
              decodeFormat,
              preferredColorSpace,
              isHardwareConfigAllowed,
              requestedWidth,
              requestedHeight,
              fixBitmapToRequestedDimensions,
              callbacks);
    //把bitmap 封裝進(jìn)Resource 滑潘,返回Resource 對象
      return BitmapResource.obtain(result, bitmapPool);
    } finally {
      releaseOptions(bitmapFactoryOptions);
      byteArrayPool.put(bytesForOptions);
    }
  }

3.9.8 DownSampler.decodeFromWrappedStreams()

下面進(jìn)入到decodeFromWrappedStreams 來看一下垢乙,這里涉及到bitmap在bitmapPool中的復(fù)用(==圖片復(fù)用僅支持大小相同的位圖==),目的是 如果bitmapPool 有可用的bitmap语卤,就復(fù)用該bitmap追逮。避免為Bitmap 分配內(nèi)存,導(dǎo)致內(nèi)存抖動(dòng)


  private Bitmap decodeFromWrappedStreams(
      ImageReader imageReader,
      BitmapFactory.Options options,
      DownsampleStrategy downsampleStrategy,
      DecodeFormat decodeFormat,
      PreferredColorSpace preferredColorSpace,
      boolean isHardwareConfigAllowed,
      int requestedWidth,
      int requestedHeight,
      boolean fixBitmapToRequestedDimensions,
      DecodeCallbacks callbacks)
      throws IOException {
    long startTime = LogTime.getLogTime();

    int[] sourceDimensions = getDimensions(imageReader, options, callbacks, bitmapPool);
    int sourceWidth = sourceDimensions[0];
    int sourceHeight = sourceDimensions[1];
    String sourceMimeType = options.outMimeType;

  
    if (sourceWidth == -1 || sourceHeight == -1) {
      isHardwareConfigAllowed = false;
    }

    int orientation = imageReader.getImageOrientation();
    int degreesToRotate = TransformationUtils.getExifOrientationDegrees(orientation);
    boolean isExifOrientationRequired = TransformationUtils.isExifOrientationRequired(orientation);

    int targetWidth =
        requestedWidth == Target.SIZE_ORIGINAL
            ? (isRotationRequired(degreesToRotate) ? sourceHeight : sourceWidth)
            : requestedWidth;
    int targetHeight =
        requestedHeight == Target.SIZE_ORIGINAL
            ? (isRotationRequired(degreesToRotate) ? sourceWidth : sourceHeight)
            : requestedHeight;

    ImageType imageType = imageReader.getImageType();
//計(jì)算縮放比例粹舵,結(jié)果會(huì)體現(xiàn)在options參數(shù)中
    calculateScaling(
        imageType,
        imageReader,
        callbacks,
        bitmapPool,
        downsampleStrategy,
        degreesToRotate,
        sourceWidth,
        sourceHeight,
        targetWidth,
        targetHeight,
        options);
    calculateConfig(
        imageReader,
        decodeFormat,
        isHardwareConfigAllowed,
        isExifOrientationRequired,
        options,
        targetWidth,
        targetHeight);
//計(jì)算sdk版本是否大于KITKAT钮孵,在該系統(tǒng)及之前 圖片復(fù)用僅支持大小相同的位圖 
    boolean isKitKatOrGreater = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
    // Prior to KitKat, the inBitmap size must exactly match the size of the bitmap we're decoding.
     //下面的判斷,來計(jì)算是否在BitmapPool中 是否有bitmap可以被復(fù)用眼滤,如果有就把bitmap 設(shè)置到options.inBitmap巴席,
     //這樣在根據(jù)options 去解析生成bitmap的時(shí)候,就不需要再次分配內(nèi)存了诅需,
    if ((options.inSampleSize == 1 || isKitKatOrGreater) && shouldUsePool(imageType)) {
      int expectedWidth;
      int expectedHeight;
      if (sourceWidth >= 0
          && sourceHeight >= 0
          && fixBitmapToRequestedDimensions
          && isKitKatOrGreater) {
        expectedWidth = targetWidth;
        expectedHeight = targetHeight;
      } else {
        float densityMultiplier =
            isScaling(options) ? (float) options.inTargetDensity / options.inDensity : 1f;
        int sampleSize = options.inSampleSize;
        int downsampledWidth = (int) Math.ceil(sourceWidth / (float) sampleSize);
        int downsampledHeight = (int) Math.ceil(sourceHeight / (float) sampleSize);
        expectedWidth = Math.round(downsampledWidth * densityMultiplier);
        expectedHeight = Math.round(downsampledHeight * densityMultiplier);

    
    
      if (expectedWidth > 0 && expectedHeight > 0) {
      //該函數(shù)會(huì)在bitmapPool中查找符合大小的bitmap 漾唉,如果找到了就設(shè)置給inBitmap
        setInBitmap(options, bitmapPool, expectedWidth, expectedHeight);
      }
    }
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
      boolean isP3Eligible =
          preferredColorSpace == PreferredColorSpace.DISPLAY_P3
              && options.outColorSpace != null
              && options.outColorSpace.isWideGamut();
      options.inPreferredColorSpace =
          ColorSpace.get(isP3Eligible ? ColorSpace.Named.DISPLAY_P3 : ColorSpace.Named.SRGB);
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
      options.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.SRGB);
    }
//根據(jù)options 把流解析為Bitmap
    Bitmap downsampled = decodeStream(imageReader, options, callbacks, bitmapPool);
    callbacks.onDecodeComplete(bitmapPool, downsampled);
    Bitmap rotated = null;
    if (downsampled != null) {
   
      downsampled.setDensity(displayMetrics.densityDpi);

      rotated = TransformationUtils.rotateImageExif(bitmapPool, downsampled, orientation);
      if (!downsampled.equals(rotated)) {
        bitmapPool.put(downsampled);
      }
    }
//rotated就是最后解析后的bitmap。
    return rotated;
  }

至此已經(jīng)得到了解析后的資源了诱担,接下來就是要顯示到指定的ImageView控件上.

4.1
接下來就是==將怎樣將bitmap顯示到控件的邏輯了毡证。==

DecodeJob.decodeFromRetrievedData()

回到DecodeJob的decodeFromRetrievedData方法,解碼后的resource不等于null時(shí)蔫仙,調(diào)用notifyEncodeAndRelease方法:

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

4.2

DecodeJob.notifyEncodeAndRelease

緩存資源料睛,通知主線程顯示

  private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {
    if (resource instanceof Initializable) {
      ((Initializable) resource).initialize();
    }

    Resource<R> result = resource;
    LockedResource<R> lockedResource = null;
    if (deferredEncodeManager.hasResourceToEncode()) {
      lockedResource = LockedResource.obtain(resource);
      result = lockedResource;
    }
// 通知主線程回調(diào),加載圖片
    notifyComplete(result, dataSource);
  // 更新狀態(tài)為編碼
    stage = Stage.ENCODE;
    try {
      if (deferredEncodeManager.hasResourceToEncode()) {
       //將轉(zhuǎn)碼好的資源緩存到磁盤摇邦,這就是磁盤的額資源緩存恤煞。
        deferredEncodeManager.encode(diskCacheProvider, options);
      }
    } finally {
      if (lockedResource != null) {
        lockedResource.unlock();
      }
    }
 
    onEncodeComplete();
  }

4.2.1 執(zhí)行DecodeJob.notifyComplete() 將resourse回調(diào)到 EngineJob的onResourceReady()

  private void notifyComplete(Resource<R> resource, DataSource dataSource) {
    setNotifiedOrThrow();
    //這個(gè)callback 就是 EngineJob對象,是在創(chuàng)建Decodejob的時(shí)候傳遞進(jìn)來
    callback.onResourceReady(resource, dataSource);
  }

4.3 EngineJob.onResourceReady()

接下來看EngineJob中onResourceReady方法:

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

4.4 EngineJob.notifyCallbacksOfResult()

public  void notifyCallbacksOfResult() {
    ResourceCallbacksAndExecutors copy;
    Key localKey;
    EngineResource<?> localResource;
    synchronized (this) {
      stateVerifier.throwIfRecycled();
      ...
      engineResource = engineResourceFactory.build(resource, isCacheable, key, resourceListener);
 
      hasResource = true;
      copy = cbs.copy();
      incrementPendingCallbacks(copy.size() + 1);

      localKey = key;
      localResource = engineResource;
    }
 //這里就是把解析后的圖片,也就是即將要顯示出來的圖片施籍,緩存到弱引用緩存中
    engineJobListener.onEngineJobComplete(this, localKey, localResource);

    for (final ResourceCallbackAndExecutor entry : copy) {
     //遍歷每一個(gè)回調(diào)接口居扒,entry.cb 就是SingleRequest 對象,執(zhí)行接口ResourceCallback的run方法
      entry.executor.execute(new CallResourceReady(entry.cb));
    }
    decrementPendingCallbacks();
  }

看下CallResourceReady接口丑慎,定義在EngineJob中:

private class CallResourceReady implements Runnable {

    private final ResourceCallback cb;

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

    @Override
    public void run() {
    
      synchronized (cb.getLock()) {
        synchronized (EngineJob.this) {
          if (cbs.contains(cb)) {
        
            engineResource.acquire();
            //執(zhí)行回調(diào)
            callCallbackOnResourceReady(cb);
            removeCallback(cb);
          }
          decrementPendingCallbacks();
        }
      }
    }
  }
 
  void callCallbackOnResourceReady(ResourceCallback cb) {
    try {
     //cb 就是SingleRequest 對象喜喂,所以下面去它里面看onResourceReady
      cb.onResourceReady(engineResource, dataSource);
    } catch (Throwable t) {
      throw new CallbackException(t);
    }
  }

SingleRequest對象的onResourceReady方法,他是ResourceCallback接口定義方法

  public void onResourceReady(Resource<?> resource, DataSource dataSource) {
    stateVerifier.throwIfRecycled();
    Resource<?> toRelease = null;
    ...
        onResourceReady((Resource<R>) resource, (R) received, dataSource);

    } finally {
      if (toRelease != null) {
        engine.release(toRelease);
      }
    }
  }

  private void onResourceReady(Resource<R> resource, R result, DataSource dataSource) {

    boolean isFirstResource = isFirstReadyResource();
    status = Status.COMPLETE;
    this.resource = resource;


    isCallingCallbacks = true;
    try {
    ...
      if (!anyListenerHandledUpdatingTarget) {
        Transition<? super R> animation = animationFactory.build(dataSource, isFirstResource);
        
//target 函數(shù)是在 buildTarget 時(shí)竿裂,創(chuàng)建的
        target.onResourceReady(result, animation);
      }
    } finally {
      isCallingCallbacks = false;
    }

    notifyLoadSuccess();
  }

ImageViewTarget的onResourceReady方法玉吁,ImageViewTarget是一個(gè)抽象類,BitmapImageViewTarget繼承它

 @Override
  public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {
    if (transition == null || !transition.transition(resource, this)) {
      setResourceInternal(resource);
    } else {
      maybeUpdateAnimatable(resource);
    }
  }


  private void setResourceInternal(@Nullable Z resource) {
  //抽象方法腻异,執(zhí)行不同的實(shí)現(xiàn)进副,我們是以BitmapImageViewTarget為例:
    setResource(resource);
    maybeUpdateAnimatable(resource);
  }

  private void maybeUpdateAnimatable(@Nullable Z resource) {
    if (resource instanceof Animatable) {
      animatable = (Animatable) resource;
      animatable.start();
    } else {
      animatable = null;
    }
  }

  protected abstract void setResource(@Nullable Z resource);
}

BitmapImageViewTarget中顯示資源,把圖片設(shè)置到ImageView中

   */
  @Override
  protected void setResource(Bitmap resource) {
    view.setImageBitmap(resource);
  }

終于啃完了悔常,比較費(fèi)事影斑,如果發(fā)現(xiàn)哪里有錯(cuò)誤给赞,煩請指出~~~加油,奧利蓋~~~
至此矫户,完結(jié)...

















最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末片迅,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子吏垮,更是在濱河造成了極大的恐慌障涯,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件膳汪,死亡現(xiàn)場離奇詭異,居然都是意外死亡九秀,警方通過查閱死者的電腦和手機(jī)遗嗽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鼓蜒,“玉大人痹换,你說我怎么就攤上這事《嫉” “怎么了娇豫?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長畅厢。 經(jīng)常有香客問我冯痢,道長,這世上最難降的妖魔是什么框杜? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任浦楣,我火速辦了婚禮,結(jié)果婚禮上咪辱,老公的妹妹穿的比我還像新娘振劳。我一直安慰自己,他們只是感情好油狂,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布历恐。 她就那樣靜靜地躺著,像睡著了一般专筷。 火紅的嫁衣襯著肌膚如雪弱贼。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天仁堪,我揣著相機(jī)與錄音哮洽,去河邊找鬼。 笑死弦聂,一個(gè)胖子當(dāng)著我的面吹牛鸟辅,可吹牛的內(nèi)容都是我干的氛什。 我是一名探鬼主播,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼匪凉,長吁一口氣:“原來是場噩夢啊……” “哼枪眉!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起再层,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤贸铜,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后聂受,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蒿秦,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年蛋济,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了棍鳖。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,115評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡碗旅,死狀恐怖渡处,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布竭贩,位于F島的核電站,受9級特大地震影響醇份,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜叮喳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一被芳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧馍悟,春花似錦畔濒、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至毅整,卻和暖如春趣兄,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背悼嫉。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工艇潭, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓蹋凝,卻偏偏與公主長得像鲁纠,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子鳍寂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 上兩一篇文章從源碼角度深入理解Glide(上)中改含,我們了解了Glide框架中的一些用法,并且分析了Glide的wi...
    maoqitian閱讀 901評論 1 2
  • 上兩篇文章從源碼角度深入理解Glide(上)和從源碼角度深入理解Glide(中)中迄汛,我們已經(jīng)把Glide加載圖片的...
    maoqitian閱讀 691評論 2 3
  • 一捍壤、LruCache 要分析Glide的源碼,首先就需要分析LruCache鞍爱。LruCache是基于LinkedH...
    zzq_nene閱讀 453評論 0 1
  • Glide基本用法 with()源碼解析 with方法根據(jù)傳入?yún)?shù)不同有以下幾種重載方法 會(huì)根據(jù)上面?zhèn)魅氲膮?shù)不一...
    刺雒閱讀 1,792評論 0 2
  • 序言 在Android開發(fā)過程中,圖片處理是必不可少的唯卖,圖片處理可繁可簡。目前有也出現(xiàn)了很多優(yōu)秀的圖片加載庫躬柬,如G...
    左大人閱讀 576評論 1 4