Glide源码分析,这篇就够了

提示:Glide源码比较多,也比较复杂,多看几遍就懂了。加油~~

一般用法:

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

一 、with方法

1.1 Glide.with()

with()方法是Glide类中的一组静态方法,返回RequestManager对象,它有好几个方法重载,我们来看一下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) {

    //必须要有一个上下文才能加载
    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){
 
  ...
  //创建RequestManagerRetriever.RequestManagerFactory
   RequestManagerRetriever.RequestManagerFactory factory =
        annotationGeneratedModule != null
            ? annotationGeneratedModule.getRequestManagerFactory()
            : null;
    builder.setRequestManagerFactory(factory);
  //这个builder就是GlideBuilder,用来构建Glide对象
         Glide glide = builder.build(applicationContext);
  }

1.4 接着看GlideBuilder类中build方法:


  @NonNull
  Glide build(@NonNull Context context) {
  //sourceExecutor是进行网络请求的执行器
    if (sourceExecutor == null) {
      sourceExecutor = GlideExecutor.newSourceExecutor();
    }
    //diskCacheExecutor磁盘缓存执行器,后面从磁盘获取缓存数据用到
    if (diskCacheExecutor == null) {
      diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
    }

    if (animationExecutor == null) {
      animationExecutor = GlideExecutor.newAnimationExecutor();
    }

    if (memorySizeCalculator == null) {
      memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
    }

    if (connectivityMonitorFactory == null) {
      connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();
    }

    if (bitmapPool == null) {
      int size = memorySizeCalculator.getBitmapPoolSize();
      if (size > 0) {
        bitmapPool = new LruBitmapPool(size);
      } else {
        bitmapPool = new BitmapPoolAdapter();
      }
    }

    if (arrayPool == null) {
      arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes());
    }

    if (memoryCache == null) {
      memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
    }

    if (diskCacheFactory == null) {
      diskCacheFactory = new InternalCacheDiskCacheFactory(context);
    }
//构建执行引擎
    if (engine == null) {
      engine =
          new Engine(
              memoryCache,
              diskCacheFactory,
              diskCacheExecutor,
              sourceExecutor,
              GlideExecutor.newUnlimitedSourceExecutor(),
              animationExecutor,
              isActiveResourceRetentionAllowed);
    }

    if (defaultRequestListeners == null) {
      defaultRequestListeners = Collections.emptyList();
    } else {
      defaultRequestListeners = Collections.unmodifiableList(defaultRequestListeners);
    }
    //构建了一个RequestManagerRetriever对象
    RequestManagerRetriever requestManagerRetriever =
        new RequestManagerRetriever(requestManagerFactory);
        
//构建Glide对象,并将上面初始化时创建的各种功能类封装进去
    return new Glide(
        context,
        engine,
        memoryCache,
        bitmapPool,
        arrayPool,
        requestManagerRetriever,
        connectivityMonitorFactory,
        logLevel,
        defaultRequestOptionsFactory,
        defaultTransitionOptions,
        defaultRequestListeners,
        isLoggingRequestOriginsEnabled,
        isImageDecoderEnabledForBitmaps);
  }

以上就是初始化Glide、并构建Engine对象、还有各种线程池、各种缓存执行器等

1.5 RequestManagerRetriever.get()

接着上面继续,通过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()) {
    //如果是是在子线程执行,让走ApplicationContext的get方法,也就是说生命周期跟application保持一致。else里面先判断activity是否destroyed
      return get(activity.getApplicationContext());
    } else {
      assertNotDestroyed(activity);
      android.app.FragmentManager fm = activity.getFragmentManager();
        //fragmentGet方法里面将glide内置的一个不可见的fragment跟当前的activity绑定
      return fragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
    }
  }
  

以传入上下文是Activity为例,继续查看是怎么得到RequestManager的,factory就是RequestManagerFactory对象

  private RequestManager fragmentGet(
      @NonNull Context context,
      @NonNull android.app.FragmentManager fm,
      @Nullable android.app.Fragment parentHint,
      boolean isParentVisible) {
      //这个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的生命周期监听类
    
          factory.build(
              glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
      current.setRequestManager(requestManager);
    }
    return requestManager;
  }

RequestManagerFactory是一个接口,build方法的参数里面传入了Lifecycle对象。这个Lifecycle是用来监听内潜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类中看似有很多个get()方法的重载,什么Context参数,Activity参数,Fragment参数等等,实际上只有两种情况而已,即传入Application类型的参数,和传入非Application类型的参数。

  2. 如果在Glide.with()方法中传入的是一个Application对象,它自动就是和应用程序的生命周期是同步的,如果应用程序关闭的话,Glide的加载也会同时终止。

  3. 如果在Glide.with()方法中传入非Application参数,那就是会向当前的Activity当中添加一个隐藏的Fragment,这个隐藏的Fragment的生命周期就和当前Activity的生命周期绑定了。

  4. 如果我们是在非主线程当中使用的Glide,那么不管你是传入的Activity还是Fragment,都会被强制当成Application来处理。

  5. 界面不可见或者销毁的时候,通过这样的方法还能避免Glide持有Activity的实例而发生内存泄漏问题。

小结:

with()方法传入当前环境,是为了让图片加载保持生命周期同步。并且返回RequestManager对象供load()方法使用。RequestManager能够用于管理和启动对Glide的请求。还可以控制生命周期事件智能地停止,启动和重新启动请求.


2、load()方法

2.1 RequestManager.load()

因为gilde支持很多图片来源。所以load方法也有很多重栽方法。
load()方法是在RequestManager里面。

//加载Bitmap
 public RequestBuilder load(@Nullable Bitmap bitmap) {
    return asDrawable().load(bitmap);
  }
 //加载Drawable
    @Override
  public RequestBuilder load(@Nullable Drawable drawable) {
    return asDrawable().load(drawable);
  }
  //加载字符串地址
   @Override
  public RequestBuilder load(@Nullable String string) {
    return asDrawable().load(string);
  }
   //加载字uri
 @Override
  public RequestBuilder load(@Nullable Uri uri) {
    return asDrawable().load(uri);
  }
   //加载字File
 @Override
  public RequestBuilder load(@Nullable File file) {
    return asDrawable().load(file);
  }
   //加载字本地图资源
 @Override
  public RequestBuilder load(@RawRes @DrawableRes @Nullable Integer resourceId) {
    return asDrawable().load(resourceId);
  }
   //加载字url
  @Override
  @Deprecated
  public RequestBuilder load(@Nullable URL url) {
    return asDrawable().load(url);
  }
  //加载字字节数组
  @Override
  public RequestBuilder load(@Nullable byte[] model) {
    return asDrawable().load(model);
  }

//我们如果不指定类型的话,默认是Drawable
  public RequestBuilder asDrawable() {
    return as(Drawable.class);
  }
 //如果需要显示gif时
  public RequestBuilder asGif() {
    return as(GifDrawable.class).apply(DECODE_TYPE_GIF);
  }
   //如果需要显示Bitmap时
  public RequestBuilder asBitmap() {
    return as(Bitmap.class).apply(DECODE_TYPE_BITMAP);
  }
  public  RequestBuilder as(
      @NonNull Class resourceClass) {
    return new RequestBuilder<>(glide, this, resourceClass, context);
  }

as asDrawable()返回的就是RequestBuilder对象。
我们以网络获取图片为例,传入String,看在RequestBuilder类里面的load方法


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

loadGeneric方法返回RequestBuilder本身,mode就是传入的加载类型,也就是字符串,将mode赋值给RequestBuilder的成员变量。
isModelSet是后面用来判断调用into方法的,必须在into之前调用load方法。

2.2 RequestBuilder


public class RequestBuilder extends BaseRequestOptions>{

  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 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里面就是一些需要的配置
比如:设置是否跳过缓存,是否磁盘缓存,展位图等。我们传入自己的配置即可。

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

小结

1、load方法用来传入加载的图片资源路径。

2、再调load方法之前需要设置请求类型是gif或者Bitmap,不设置默认时Drawable。

3、load之后需要设置请求的一些配置参数。是否使用缓存,展位图等。

4、最终返回的是配置好请求类型的RequestBuilder,用来进行下一步into调用。


3、into()方法

3.1 RequestBuilder.into()

@NonNull
  public ViewTarget 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(
        //构建Target:DrawableImageViewTarget(view)或者是BitmapImageViewTarget(view)
        //因为我们默认是Drawable,所以transcodeClass是Drawable.class
        glideContext.buildImageViewTarget(view, transcodeClass),
        /*targetListener=*/ null,
        //配置好的请求参数
        requestOptions,
        //主线程执行器,Executors的构造方法里面有:Handler handler = new Handler(Looper.getMainLooper());
        Executors.mainThreadExecutor());
  }

看一下GlideContext的buildImageViewTarget方法,参数是我们的控件View和最终转码类型的字节码
GlideContext类是在Glide初始化的最后构建的,用来全局提供Glide构建的配置类对象的,比如它的getEngine()方法,返回Engine对象。

3.1.1 GlideContext.buildImageViewTarget

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

3.1.2 ImageViewTargetFactory.buildTarget
通过传入的资源转码类型去创建不同的Target:
new BitmapImageViewTarget(view)和
new DrawableImageViewTarget(view);

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

3.1.3 DrawableImageViewTarget

看下DrawableImageViewTarget类,有个setResource()方法,这玩意应该就是最后将获取到的资源图片显示到控件的方法了。

public class DrawableImageViewTarget extends ImageViewTarget {

  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()
构造器里创建了主线程的handle对象,再exectue执行后,handle.post(command)将数据传递到主线程

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;
 

继续return的into方法

3.2 RequestBuilder.into()

  private > Y into(
    //在GlideContext中创建的target
      @NonNull Y target,
        //null
      @Nullable RequestListener targetListener,
      //requestBuilder配置的参数
      BaseRequestOptions options,
        //主线程执行器
      Executor callbackExecutor) {
      
    Preconditions.checkNotNull(target);
    //isModelSet的作用。
    if (!isModelSet) {
      throw new IllegalArgumentException("You must call #load() before calling #into()");
    }
    //通过我们传入的参数调buildRequest方法,返回一个request,callbackExecutor含有绑定主线程的Handler
    Request request = buildRequest(target, targetListener, options, callbackExecutor);
    //在给target设置request之前,看下这个target之前有没有老的request。
    Request previous = target.getRequest();
    //如果两个request等价,并且老的request有设置缓存,并且老request的不为null,并且不在Running中,就调用request的begin()方法,让他开始加载。并返回这个target。
    if (request.isEquivalentTo(previous)
        && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
     
      if (!Preconditions.checkNotNull(previous).isRunning()) {
    
        previous.begin();
      }
      return target;
    }
    //如果上面判断不成立。则clear老的request,将新的request设置给target。并且执行 requestManager.track()方法。返回target。
    requestManager.clear(target);
    ==target==.setRequest(request);
    requestManager.track(target, request);

    return target;
  }

注意:Request类是个接口,本身有start,pause,clear,isRunning,isComplete,isEquivalentTo等方法。我们这里最终返回的Request就是后面说的==SingleRequest==对象。

** 3.2.1 说这个buildRequest方法之前,解释一下requestManager.track这个方法**

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

3.2.2 看下TargetTracker类:

==TargetTracker实现LifecycleListener接口==,里面创建了一个targets集合。这个类的作用就是将所有的target添加到集合,并在生命周期变化时管理它。

public final class TargetTracker implements LifecycleListener {
// targets是一个具有映射关系的set无序集合。key就是target。
//WeakHashMap也是一种hashmap,特点就是它的key是弱键,当key不使用的时候可以被回收。

  private final Set> targets =
      Collections.newSetFromMap(new WeakHashMap, 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这个类:
==RequestTracker是个管理request的工具类==

public class RequestTracker {
    //将所有的request放入到一个有映射关系的set集合中,用来控制reuqest的行为
    private final Set requests =Collections.newSetFromMap(new WeakHashMap());
    //排队等待执行的request的集合 
    private final List pendingRequests = new ArrayList<>();
    //执行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 requests =
      Collections.newSetFromMap(new WeakHashMap());====
    requests.add(request);
    //如果没有暂停,执行request的begin方法。这里request就是后面说的SingerRequest对象。
    if (!isPaused) {
      request.begin();
    } else {
//如果在暂停,执行clear方法  :target.removeCallback(this);
      request.clear();
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        Log.v(TAG, "Paused, delaying request");
      }
      // private final List pendingRequests = new ArrayList<>();
     
      //放入挂起集合里面等待
      pendingRequests.add(request);
    }
  }

具体的执行请求逻辑在后面的SingerRequest中。

** 3.3 继续看RequestBuilder.buildRequest方法:**

private Request buildRequest(
     Target target,
     @Nullable RequestListener 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 target,
    @Nullable RequestListener targetListener,
    @Nullable RequestCoordinator parentCoordinator,
    TransitionOptions 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 target,
      RequestListener targetListener,
      @Nullable RequestCoordinator parentCoordinator,
      TransitionOptions 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 target,
      RequestListener targetListener,
      BaseRequestOptions requestOptions,
      RequestCoordinator requestCoordinator,
      TransitionOptions transitionOptions,
      Priority priority,
      int overrideWidth,
      int overrideHeight,
      Executor callbackExecutor) {
      //这才是重点,最后返回的就是这个SingleRequest对象
    return SingleRequest.obtain(
        context,
        glideContext,
        requestLock,
        model,
        transcodeClass,
        requestOptions,
        overrideWidth,
        overrideHeight,
        priority,
        target,
        targetListener,
        requestListeners,
        requestCoordinator,
        glideContext.getEngine(),
        transitionOptions.getTransitionFactory(),
        callbackExecutor);
  }

obtainRequest()方法来获取一个Request对象.obtainRequest()方法有调用了SingleRequest.obtain方法,传入之前配置好的参数各种参数。这些参数其实都是组装到Request对象中了。

3.3.2 SingleRequest

==再看下SingleRequest类==,SingleRequest.obtain的之后就是SingleRequest的初始化操作并且参数赋值。这个SingleRequest就是要返回的request。

public final class SingleRequest implements Request, SizeReadyCallback, ResourceCallback {

  private SingleRequest(
      Context context,
      GlideContext glideContext,
      @NonNull Object requestLock,
      @Nullable Object model,
      Class transcodeClass,
      BaseRequestOptions requestOptions,
      int overrideWidth,
      int overrideHeight,
      Priority priority,
      Target target,
      @Nullable RequestListener targetListener,
      @Nullable List> requestListeners,
      RequestCoordinator requestCoordinator,
      Engine engine,
      TransitionFactory 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中回调用begin方法(3.2.4中):==

  @Override
  public void begin() {
    synchronized (requestLock) {
      assertNotCallingCallbacks();
        //确定对象没有被回收
      stateVerifier.throwIfRecycled();
      startTime = LogTime.getLogTime();
       // model(url)为空,回调加载失败
      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;
      }

      //初始化状态
      status = Status.WAITING_FOR_SIZE;
      if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
       //如果已经设置好width
        onSizeReady(overrideWidth, overrideHeight);
      } else {
       //通过回调去监界面渲染完成时获取view的大小( ViewTreeObserver observer = view.getViewTreeObserver();)
       //还是会调用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大小获取到后,调用SingleRequest的onSizeReady()方法,继续:

  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 是在创建Glide的build()方法中 创建的(第一节1.4),engine封装了各种Executor,内存缓存等
      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

继续Engine的load方法:
这里开始图片的请求,图片的三级缓存的功能也在这里
这里我们先定义一下三级缓存:

1、弱引用缓存:使用弱引用,来缓存图片,图片被回收后,会保存到内存缓存中。

2、内存缓存LruCache:(默认是在创建Glide的时候创建的,也可自定义), 如果弱引用缓存找不到图片,就从内存缓存中查找,找到图片后,删除内存缓存(防止因Lru的策略,图片正在使用,但是被回收掉的问题)。

3、磁盘缓存 :上面两级缓存都没有图片,如果在磁盘缓存中找到,就把图片加载后,放到弱引用缓存中。磁盘缓存数据的种类有两种,一种是缓存源数据,这种数据需要经过解析才能得到图片。一种是图片数据,直接加载进来就可以用的。可以通过diskCacheStrategyOf 来自由选择如何缓存

 public  LoadStatus load(
      GlideContext glideContext,
      Object model,
      Key signature,
      int width,
      int height,
      Class resourceClass,
      Class transcodeClass,
      Priority priority,
      DiskCacheStrategy diskCacheStrategy,
      Map, 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,以后就根据这个key,在缓存中查找

    EngineKey key =
        keyFactory.buildKey(
            model,
            signature,
            width,
            height,
            transformations,
            resourceClass,
            transcodeClass,
            options);
            
//从内存里面找是否有目标图片(包括弱应用缓存和内存缓存)

    EngineResource memoryResource;
    synchronized (this) {
      memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);
      
//如果内存里面没有,进入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);
      }
    }
    //如果内存中能找到,则直接回调出去
    cb.onResourceReady(memoryResource, DataSource.MEMORY_CACHE);
    return null;

3.4.1

==内存中找到的话,将数据回调到SingleReuest的onResourceReady方法,最最终通过target将展示图片到控件。==

  @GuardedBy("requestLock")
  private void onResourceReady(Resource resource, R result, DataSource dataSource) {
    // We must call isFirstReadyResource before setting status.
    boolean isFirstResource = isFirstReadyResource();
    status = Status.COMPLETE;
    this.resource = resource;
...
      if (!anyListenerHandledUpdatingTarget) {
        Transition animation = animationFactory.build(dataSource, isFirstResource);
        
//在这里,通过我们之前创建的DrawableImageViewTarget,他继承自ImageViewTarget,ImageViewTarget有个抽象方法就是onResourceReady(),最终将将图片显示到控件上。
        target.onResourceReady(result, animation);
      }
    } finally {
      isCallingCallbacks = false;
    }

    notifyLoadSuccess();
  }

3.5 从内存里面找

  @Nullable
  private EngineResource loadFromMemory(
      EngineKey key, boolean isMemoryCacheable, long startTime) {
    if (!isMemoryCacheable) {
      return null;
    }
 //检查是弱引用缓存中否有目标图片
    EngineResource active = loadFromActiveResources(key);
    if (active != null) {
      if (VERBOSE_IS_LOGGABLE) {
        logWithTimeAndKey("Loaded resource from active resources", startTime, key);
      }
      return active;
    }
//检查内存的缓存 是否有目标图片
    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获取弱应用缓存
    EngineResource active = activeResources.get(key);
    if (active != null) {
      active.acquire();
    }

    return active;
  }

3.5.2 ActiveResources 弱引用缓存

class ActiveResources {
//这个map就是ActiveResources里面用来保存弱应用缓存的
Map activeEngineResources = new HashMap<>();

 @Nullable
 synchronized EngineResource get(Key key) {
  
    ResourceWeakReference activeRef = activeEngineResources.get(key);
    if (activeRef == null) {
      return null;
    }
//找到弱应用对象,get到EngineResource返回
    EngineResource active = activeRef.get();
    if (active == null) {
      cleanupActiveReference(activeRef);
    }
    return active;
  }
  
  
//ResourceWeakReference是ActiveResources的内部类,继承WeakReference
static final class ResourceWeakReference extends WeakReference> {
    final Key key;//缓存key
    final boolean isCacheable;
    Resource resource;//缓存resource
}


 

ActiveResources是保存活动资源的一个类,它里面有个内部类ResourceWeakReference,这个ResourceWeakReference继承WeakReference。
这个ActiveResources里面有一个value是ResourceWeakReference类型的map,它主要保存的就是活动的资源,我们叫他弱应用缓存。缓存是先从弱应用缓存中查找,没找到再去内存缓存中查找。

再看下这个弱应用缓存是什么时候存进去的?

//1、弱应用缓存没找到,就会去内存缓存找,内存缓存找到后保存到弱应用缓存
 private EngineResource loadFromCache(Key key) {
    EngineResource cached = getEngineResourceFromCache(key);
    if (cached != null) {
      cached.acquire();
      //这个方法就是往弱应用缓存map中存数据
      activeResources.activate(key, cached);
    }
    return cached;
  }
  
  
  //2、当内存缓存中都没有找到,那就去磁盘中找,在没有的就去网络获取,这时候获取到资源并且展示完成后再存到弱应用缓存中。
  
  @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 如果缓存里面没有,则走下面方法,从磁盘或者网络获取

//执行一个新的job
 private  LoadStatus waitForExistingOrStartNewJob(
    GlideContext glideContext,
    Object model,
    Key signature,
    int width,
    int height,
    Class resourceClass,
    Class transcodeClass,
    Priority priority,
    DiskCacheStrategy diskCacheStrategy,
    Map, Transformation> transformations,
    boolean isTransformationRequired,
    boolean isScaleOnlyOrNoTransform,
    Options options,
    boolean isMemoryCacheable,
    boolean useUnlimitedSourceExecutorPool,
    boolean useAnimationPool,
    boolean onlyRetrieveFromCache,
    ResourceCallback cb,
    Executor callbackExecutor,
    EngineKey key,
    long startTime) {
//在弱引用和内存缓存中,都没有找到图片,就执行任务。
//这个任务,会现在磁盘缓存中查找,因为磁盘读取耗时较大,所以放在任务线程中
  EngineJob current = jobs.get(key, onlyRetrieveFromCache);
  //如果current不等于null,说明这个engineJob已经在执行了,不用再次构建
  if (current != null) {
    current.addCallback(cb, callbackExecutor);
    if (VERBOSE_IS_LOGGABLE) {
      logWithTimeAndKey("Added to existing load", startTime, key);
    }
    return new LoadStatus(cb, current);
  }
//创建一个新的engineJob对象,它里面有很多Executor,用来加载异步图片
  EngineJob engineJob =
      engineJobFactory.build(
          key,
          isMemoryCacheable,
          useUnlimitedSourceExecutorPool,
          useAnimationPool,
          onlyRetrieveFromCache);
//创建一个解码工作的decodeJob,用于解码图片的
  DecodeJob decodeJob =
      decodeJobFactory.build(
          glideContext,
          model,
          key,
          signature,
          width,
          height,
          resourceClass,
          transcodeClass,
          priority,
          diskCacheStrategy,
          transformations,
          isTransformationRequired,
          isScaleOnlyOrNoTransform,
          onlyRetrieveFromCache,
          options,
          engineJob);
// 放在Jobs内部维护的存放任务的HashMap中(3.6.1),
  jobs.put(key, engineJob);
// 注册ResourceCallback接口,就是在成功获取图片后,需要显示到ImageView 上的回调,这个接口回调到SingleRequest 中
  engineJob.addCallback(cb, callbackExecutor);
   //开始执行
  engineJob.start(decodeJob);

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

3.6.1 Jobs

Jobs里面维护了两个map,一个新job,一个缓存job。

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

  @VisibleForTesting
  Map> 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> jobMap = getJobMap(expected.onlyRetrieveFromCache());
    if (expected.equals(jobMap.get(key))) {
      jobMap.remove(key);
    }
  }

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

3.7 继续EngineJob中的start方法

 public synchronized void start(DecodeJob decodeJob) {
    this.decodeJob = decodeJob;
    //若能从磁盘缓存获取数据,就使用diskCacheExecutor,否则在根据其他的条件判断使用哪个Executor
    //ture:有缓存,则使用磁盘缓存线程池。否则返回数据源线程池;
    GlideExecutor executor =
        decodeJob.willDecodeFromCache() ? diskCacheExecutor : getActiveSourceExecutor();
        //执行decodeJob的run方法
    executor.execute(decodeJob);
  }

通过上面start()方法知道是去磁盘取还是网络获取,对应执行器再去执行这个decodeJob。

3.8 DecodeJob

这个类负责从磁盘或数据源解码资源,并应用转换和转码。

在看下DecodeJob的willDecodeFromCache方法:

  boolean willDecodeFromCache() {
    Stage firstStage = getNextStage(Stage.INITIALIZE);
    //如果此作业将尝试从磁盘缓存解码资源,则返回 true,如果它始终从源解码,则返回 false。
    return firstStage == Stage.RESOURCE_CACHE || firstStage == Stage.DATA_CACHE;
  }

3.8.1 获取下一个阶段从哪里获取数据

 private Stage getNextStage(Stage current) {
    switch (current) {
    //若配置的缓存策略允许从磁盘缓存的资源中读取数据,则返回Stage.RESOURCE_CACHE
      case INITIALIZE:
        return diskCacheStrategy.decodeCachedResource()
            ? Stage.RESOURCE_CACHE
            : getNextStage(Stage.RESOURCE_CACHE);
     //若配置的缓存策略允许从磁盘缓存的源数据缓存读取数据,则返回Stage.DATA_CACHE
      case RESOURCE_CACHE:
        return diskCacheStrategy.decodeCachedData()
            ? Stage.DATA_CACHE
            : getNextStage(Stage.DATA_CACHE);
     //若只能允许从缓存中读取数据,则直接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);
    }
  }

注意:磁盘缓存了两种资源,一种是数据源缓存,一种是磁盘的资源缓存

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:
        //获取下一阶段的状态
        stage = getNextStage(Stage.INITIALIZE);
         //根据下一阶段状态,判断具体有哪个类执行
        currentGenerator = getNextGenerator();
        runGenerators();
        break;
      case SWITCH_TO_SOURCE_SERVICE:
        runGenerators();
        break;
      case DECODE_DATA:
        decodeFromRetrievedData();
        break;
      default:
        throw new IllegalStateException("Unrecognized run reason: " + runReason);
    }
  }

首先从磁盘中去数据。如果磁盘的资源缓存或者磁盘的数据源缓存任意一个没有取到缓存,则就去网络请求数据。
该类继承了DataFetcherGenerator, 这是一个数据获取生成器。

  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去选择哪一个执行器。

3.8.4 DecodeJob.runGenerators()

  private void runGenerators() {
    currentThread = Thread.currentThread();
    startFetchTime = LogTime.getLogTime();
    boolean isStarted = false;
     //判断逻辑主要看startNext方法,这个方法回去执行不同执行器的startNext方法。
    // 返回值是个布尔值,如果返回true,说明刚才的执行器获取到了缓存,然后去解码,回调出去,如果返回false,则执行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() {
  //我们想从磁盘缓存服务切换到源执行器。
    runReason = RunReason.SWITCH_TO_SOURCE_SERVICE;
    callback.reschedule(this);
  }
 runReason改变之后,reschedule方法执行的就是网络获取执行器的逻辑了,

3.8.5 获取网络图片

所以执行SourceGenerator.startNext方法:

  @Override
  public boolean startNext() {
   ...

    loadData = null;
    boolean started = false;
    while (!started && hasNextModelLoader()) {
     //从DecodeHelper的数据加载集合中, 获取一个数据加载器 ModelLoader
     //这些ModelLoader 包括默认的和自定义的
      // 这里的符合条件就是判断在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> getLoadData() {
    if (!isLoadDataSet) {
      isLoadDataSet = true;
      loadData.clear();
       //从Glide注册的register中获取modelLoaders
      List> modelLoaders = glideContext.getRegistry().getModelLoaders(model);
         //遍历modelLoaders
      for (int i = 0, size = modelLoaders.size(); i < size; i++) {
      //此时的model为url的string格式,返回该其中一个实现类为StringLoader 
        ModelLoader modelLoader = modelLoaders.get(i);
         //通过函数buildLoadData 来创建LoadData
        LoadData current = modelLoader.buildLoadData(model, width, height, options);
        if (current != null) {
          loadData.add(current);
        }
      }
    }
    return loadData;
  }

3.8.7 startNextLoad()

继续查看 startNextLoad()方法接着通过LoadData对象内部的 fetcher ,来进行实际的请求操作(例如发起网络请求)

private void startNextLoad(final LoadData toStart) {
   loadData.fetcher.loadData(
       helper.getPriority(),
       new DataCallback() {
         @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逻辑,他是最终获取资源的,比如网络请求数据,fetcher是HttpUrlFetcher:

 @Override
public void loadData(
    @NonNull Priority priority, @NonNull DataCallback callback) {
  long startTime = LogTime.getLogTime();
  try {
  //网络请求数据
    InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
    //数据获取成功的回调
    callback.onDataReady(result);
  } catch (IOException e) {

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

** 3.8.9 **

执行网络请求返回数据流

 private InputStream loadDataWithRedirects(
      URL url, int redirects, URL lastUrl, Map 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 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 **

请求数据成功后, callback.onDataReady(result)在SourceGenerator的startNextLoad里面(3.8.7)接收回调数据,

private void startNextLoad(final LoadData toStart) {
    loadData.fetcher.loadData(
        helper.getPriority(),
        new DataCallback() {
          @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 **

这时候数据已经请求到了,执行onDataReadyInternal方法,参数有loadDate和请求到的数据

  @SuppressWarnings("WeakerAccess")
  @Synthetic
  void onDataReadyInternal(LoadData loadData, Object data) {
    DiskCacheStrategy diskCacheStrategy = helper.getDiskCacheStrategy();
    //如果该数据类型,有启用磁盘缓存,就把值赋给dataToCache
    if (data != null && diskCacheStrategy.isDataCacheable(loadData.fetcher.getDataSource())) {
      dataToCache = data;
      //调用DecodeJob的reschedule,用线程池执行任务,实际上就是再次调用SourceGenerator的startNext
      cb.reschedule();
    } else {
     // 继续回调FetcherReadyCallback的onDataFetcherReady方法,将data回调出去
      cb.onDataFetcherReady(
          loadData.sourceKey,
          data,
          loadData.fetcher,
          loadData.fetcher.getDataSource(),
          originalKey);
    }
  }

3.9.1 解析数据

这个回调方法走的是DecodeJob.onDataFetcherReady(),DecodeJob类实现了FetcherReadyCallback接口。
然后解析数据

 @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 {
      //解析获取到的数据
        decodeFromRetrievedData();
      } finally {
        GlideTrace.endSection();
      }
    }
  }

3.9.2

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

  private void decodeFromRetrievedData() {

    Resource resource = null;
    try {
     // 从数据中解码得到资源
      resource = decodeFromData(currentFetcher, currentData, currentDataSource);
    } catch (GlideException e) {
   ...
    }
     // 最终得到的Resource对象,
    if (resource != null) {
      notifyEncodeAndRelease(resource, currentDataSource);
    } else {
      runGenerators();
    }
  }

至此:得到了网络请求的数据,并解析后得到了资源

3.9.3

看下怎么解析数据的

  private  Resource decodeFromData(
      DataFetcher fetcher, Data data, DataSource dataSource) throws GlideException {
    try {
      if (data == null) {
        return null;
      }
      long startTime = LogTime.getLogTime();
       //继续解析数据
      Resource result = decodeFromFetcher(data, dataSource);
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        logWithTimeAndKey("Decoded result " + result, startTime);
      }
      return result;
    } finally {
      fetcher.cleanup();
    }
  }

这里的data 是一个泛型,本例中是 Stream 流,从http请求获取到的

    private  Resource decodeFromFetcher(Data data, DataSource dataSource){
  
    
    LoadPath path = decodeHelper.getLoadPath((Class) data.getClass());
    
    //通过解析器来解析数据
    return runLoadPath(data, dataSource, path);
  }
  

上面代码看出:
1、获取一个LoadPath,它是根据数据类型(这里是stream),ResourceDecoder(资源解码),transcoder(资源转码)

2、从这些参数可以看出,最终把数据流转为Bitmap 或Drawable ,就是在LoadPath中进行的,这里是指DecodePath

  private  Resource runLoadPath(
      Data data, DataSource dataSource, LoadPath path)
      throws GlideException {
    Options options = getOptionsWithHardwareConfig(dataSource);
    
    //此时的data为InputStream对象,故rewinder为InputStreamRewinder对象
    DataRewinder rewinder = glideContext.getRegistry().getRewinder(data);
    try {
    
      //执行LoadPath 的load ,进行解码,转换操作
      return path.load(
          rewinder, options, width, height, new DecodeCallback(dataSource));
    } finally {
      rewinder.cleanup();
    }
  }

3.9.4
LoadPath.load() 解析数据


  public Resource load(
      {
    ...参数省略...
      return loadWithExceptionList(rewinder, options, width, height, decodeCallback, throwables);
    } finally {
      listPool.release(throwables);
    }
  }

重点在下面方法:正真的解码


  private Resource loadWithExceptionList(
      DataRewinder rewinder,
      @NonNull Options options,
      int width,
      int height,
      DecodePath.DecodeCallback decodeCallback,
      List exceptions)
      throws GlideException {
    Resource result = null;
      //遍历DecodePath集合
    for (int i = 0, size = decodePaths.size(); i < size; i++) {
      DecodePath path = decodePaths.get(i);
      try {
        //重点:调用DecodePath.decode真正进行数据解析
        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 decode(
      DataRewinder rewinder,
      int width,
      int height,
      @NonNull Options options,
      DecodeCallback callback)
      throws GlideException {
     //获取到Resource对象  
    Resource decoded = decodeResource(rewinder, width, height, options);
      // 这个方法是回调到Decodejob.onResourceDecoded ,作用是调用RequestOptions中的Transform处理图片,然后将ResourceCache的Key和Encode准备好(放在变量 deferEncoderManager中),最后将这个源数据进行写入磁盘缓存。
//这就是磁盘的源数据缓存。
    Resource transformed = callback.onResourceDecoded(decoded);
     //进行数据类型的转换
    return transcoder.transcode(transformed, options);
  }

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

3.9.5

继续decodeResourceWithList方法:decoder是一个ResourceDecoder接口(资源解码器),根据不同的DataType和ResourceType它会有不同的实现类,这里的实现类是ByteBufferBitmapDecoder

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

    return result;
  }

3.9.6
ByteBufferBitmapDecoder的decode方法,
里面有个downsampler类,downsampler主要是对流进行解码,旋转,压缩,圆角等处理

public class ByteBufferBitmapDecoder implements ResourceDecoder {
  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 decode(
      @NonNull ByteBuffer source, int width, int height, @NonNull Options options)
      throws IOException {
    InputStream is = ByteBufferUtil.toStream(source);
    //downsampler主要是对流进行解码,旋转,压缩,圆角等处理
    return downsampler.decode(is, width, height, options);
  }
}

3.9.7
继续DownSampler中的decode方法,省去多次跳转:

 private Resource 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 封装进Resource ,返回Resource 对象
      return BitmapResource.obtain(result, bitmapPool);
    } finally {
      releaseOptions(bitmapFactoryOptions);
      byteArrayPool.put(bytesForOptions);
    }
  }

3.9.8 DownSampler.decodeFromWrappedStreams()

下面进入到decodeFromWrappedStreams 来看一下,这里涉及到bitmap在bitmapPool中的复用(==图片复用仅支持大小相同的位图==),目的是 如果bitmapPool 有可用的bitmap,就复用该bitmap。避免为Bitmap 分配内存,导致内存抖动


  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();
//计算缩放比例,结果会体现在options参数中
    calculateScaling(
        imageType,
        imageReader,
        callbacks,
        bitmapPool,
        downsampleStrategy,
        degreesToRotate,
        sourceWidth,
        sourceHeight,
        targetWidth,
        targetHeight,
        options);
    calculateConfig(
        imageReader,
        decodeFormat,
        isHardwareConfigAllowed,
        isExifOrientationRequired,
        options,
        targetWidth,
        targetHeight);
//计算sdk版本是否大于KITKAT,在该系统及之前 图片复用仅支持大小相同的位图 
    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.
     //下面的判断,来计算是否在BitmapPool中 是否有bitmap可以被复用,如果有就把bitmap 设置到options.inBitmap,
     //这样在根据options 去解析生成bitmap的时候,就不需要再次分配内存了,
    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) {
      //该函数会在bitmapPool中查找符合大小的bitmap ,如果找到了就设置给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);
    }
//根据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;
  }

至此已经得到了解析后的资源了,接下来就是要显示到指定的ImageView控件上.

4.1
接下来就是==将怎样将bitmap显示到控件的逻辑了。==

DecodeJob.decodeFromRetrievedData()

回到DecodeJob的decodeFromRetrievedData方法,解码后的resource不等于null时,调用notifyEncodeAndRelease方法:

 private void decodeFromRetrievedData() {
    if (Log.isLoggable(TAG, Log.VERBOSE)) {
      logWithTimeAndKey(
          "Retrieved data",
          startFetchTime,
          "data: "
              + currentData
              + ", cache key: "
              + currentSourceKey
              + ", fetcher: "
              + currentFetcher);
    }
    Resource 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 resource, DataSource dataSource) {
    if (resource instanceof Initializable) {
      ((Initializable) resource).initialize();
    }

    Resource result = resource;
    LockedResource lockedResource = null;
    if (deferredEncodeManager.hasResourceToEncode()) {
      lockedResource = LockedResource.obtain(resource);
      result = lockedResource;
    }
// 通知主线程回调,加载图片
    notifyComplete(result, dataSource);
  // 更新状态为编码
    stage = Stage.ENCODE;
    try {
      if (deferredEncodeManager.hasResourceToEncode()) {
       //将转码好的资源缓存到磁盘,这就是磁盘的额资源缓存。
        deferredEncodeManager.encode(diskCacheProvider, options);
      }
    } finally {
      if (lockedResource != null) {
        lockedResource.unlock();
      }
    }
 
    onEncodeComplete();
  }

4.2.1 执行DecodeJob.notifyComplete() 将resourse回调到 EngineJob的onResourceReady()

  private void notifyComplete(Resource resource, DataSource dataSource) {
    setNotifiedOrThrow();
    //这个callback 就是 EngineJob对象,是在创建Decodejob的时候传递进来
    callback.onResourceReady(resource, dataSource);
  }

4.3 EngineJob.onResourceReady()

接下来看EngineJob中onResourceReady方法:

  @Override
  public void onResourceReady(Resource 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) {
     //遍历每一个回调接口,entry.cb 就是SingleRequest 对象,执行接口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();
            //执行回调
            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) resource, (R) received, dataSource);

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

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

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


    isCallingCallbacks = true;
    try {
    ...
      if (!anyListenerHandledUpdatingTarget) {
        Transition animation = animationFactory.build(dataSource, isFirstResource);
        
//target 函数是在 buildTarget 时,创建的
        target.onResourceReady(result, animation);
      }
    } finally {
      isCallingCallbacks = false;
    }

    notifyLoadSuccess();
  }

ImageViewTarget的onResourceReady方法,ImageViewTarget是一个抽象类,BitmapImageViewTarget继承它

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


  private void setResourceInternal(@Nullable Z resource) {
  //抽象方法,执行不同的实现,我们是以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中显示资源,把图片设置到ImageView中

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

终于啃完了,比较费事,如果发现哪里有错误,烦请指出~~~加油,奥利盖~~~
至此,完结...

















你可能感兴趣的:(Glide源码分析,这篇就够了)