前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Glide源码分析(一)

Glide源码分析(一)

原创
作者头像
CatEatFish
修改2020-07-09 14:25:02
1.4K0
修改2020-07-09 14:25:02
举报
文章被收录于专栏:干活分享干活分享

Glide作为一个图片加载框架深受开发者喜欢,包体积小,加载速度快,以及加载圆角等。作为一名开发者我们有必要去了解Glide图片加载机制,它是如何把图片加载出来的?以及在图片加载过程中它都做了什么?

1. Glide.with()

代码语言:txt
复制
@NonNull

public static RequestManager with(@NonNull FragmentActivity activity) {
  // 1.调用 getRetriever 方法获取到RequestManagerRetriever
  // 2.RequestManagerRetriever.get()获取到RequestManager 图片请求管理者
  return getRetriever(activity).get(activity);
}


 @NonNull
  private static RequestManagerRetriever getRetriever(@Nullable Context context) {
   // 1.调用Glide.get()方法获取Glied对象
   // 2.调用getRequestManagerRetriever()获取到 RequestManagerRetriever
    return Glide.get(context).getRequestManagerRetriever();
  }

Glide 调用 with() 方法,可以看出主要做了两件事:

1.通过 getRetriever() 获取RequestManagerRetriever对象

  • 调用 Glide.get() 方法获取 Glied 对象
  • 调用 getRequestManagerRetriever() 得到RequestManagerRetriever 对象

2.通过 RequestManagerRetriever对象 拿到requestManage 图片请求管理者

1.1 获取 RequestManagerRetriever 对象

  1. 获取 Glied 对象
代码语言:txt
复制
public class Glide implements ComponentCallbacks2 {

  /**
  * 单利模式获取Glide对象
  */
  @NonNull
  public static Glide get(@NonNull Context context) {
    if (glide == null) {
      synchronized (Glide.class) {
        if (glide == null) {
          checkAndInitializeGlide(context);
        }
      }
    }
    return glide;
  }
   private static void checkAndInitializeGlide(@NonNull Context context) {
    if (isInitializing) {
      throw new IllegalStateException("You cannot call Glide.get() in registerComponents(),"
          + " use the provided Glide instance instead");
    }
    //防止多次调用Glide.get()方法
    isInitializing = true;
    initializeGlide(context);
    isInitializing = false;
  }
  private static void initializeGlide(@NonNull Context context) {
    initializeGlide(context, new GlideBuilder());
  }

  private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
    Context applicationContext = context.getApplicationContext();
    // 1.获取 @GlideModule 注解驱动生成的 GeneratedAppGlideModuleImpl 和 GeneratedAppGlideModuleFactory 类
    GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules();
    // 2.从annotationGeneratedModule中获取RequestManager构造工厂对象
    RequestManagerRetriever.RequestManagerFactory factory =
        annotationGeneratedModule != null
            ? annotationGeneratedModule.getRequestManagerFactory() : null;
    // 3.添加到 GlideBuilder 中
    builder.setRequestManagerFactory(factory);
    // 4.构造 glide 对象
    Glide glide = builder.build(applicationContext);
    // 5. 向 Application 中注册一个组件的回调, 用于检测系统 Config 改变和内存占用量低的信号
    applicationContext.registerComponentCallbacks(glide);
    // 6.保存为静态常量
    Glide.glide = glide;
  }
  

在initializeGlide()方法中获取 @GlideModule 注解生成类,然后获取到获取RequestManager构造工厂对象,添加到 GlideBuilder 中,构造出glide对象

具体看看glied对象创建过程:

代码语言:txt
复制
public final class GlideBuilder {
  // 1.线程池
  private GlideExecutor sourceExecutor;
  private GlideExecutor diskCacheExecutor;
  private GlideExecutor animationExecutor;
  // 2.缓存大小设置
  private MemorySizeCalculator memorySizeCalculator;
  // 3.图片享元复用池
  private BitmapPool bitmapPool;
  private ArrayPool arrayPool;
  // 4.缓存策略
  private MemoryCache memoryCache;
  // 5.资源管理与程池的引擎
  private Engine engine;
 


 
  // 6.设置默认的 RequestOptions
  private RequestOptions defaultRequestOptions = new RequestOptions();
  // 7. 磁盘缓存和请求构建工厂
  private DiskCache.Factory diskCacheFactory;
  private RequestManagerFactory requestManagerFactory;
  
  ......
    
   Glide build(@NonNull Context context) {
   // 1.1 网络操作使用线程池
    if (sourceExecutor == null) {
      sourceExecutor = GlideExecutor.newSourceExecutor();
    }
    // 1.2磁盘缓存线程池
    if (diskCacheExecutor == null) {
      diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
    }
    // 1.3 执行动画线程池
    if (animationExecutor == null) {
      animationExecutor = GlideExecutor.newAnimationExecutor();
    }
    // 2.1 基于屏幕分辨率,宽高等条件设置缓存大小
    if (memorySizeCalculator == null) {
      memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
    }
    // 3.1 bitmap 复用池
    if (bitmapPool == null) {
      int size = memorySizeCalculator.getBitmapPoolSize();
    }
    // 3.2 数组复用池
    if (arrayPool == null) {
      arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes());
    }
    // 4.1内存缓存策略
    if (memoryCache == null) {
      memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
    }
    // 4.2 磁盘缓存工厂
    if (diskCacheFactory == null) {
      diskCacheFactory = new InternalCacheDiskCacheFactory(context);
    }
    // 5.资源管理与程池的引擎
    if (engine == null) {
      engine =
          new Engine(
              memoryCache,
              diskCacheFactory,
              diskCacheExecutor,
              sourceExecutor,
              GlideExecutor.newUnlimitedSourceExecutor(),
              GlideExecutor.newAnimationExecutor(),
              isActiveResourceRetentionAllowed);
    }
    // 6.创建了一个 RequestManagerRetriever对象
    RequestManagerRetriever requestManagerRetriever =
        new RequestManagerRetriever(requestManagerFactory);
    // 7.创建了Glide对象
    return new Glide(
        context,
        engine,
        memoryCache,
        bitmapPool,
        arrayPool,
        requestManagerRetriever,
        connectivityMonitorFactory,
        logLevel,
        defaultRequestOptions.lock(),
        defaultTransitionOptions,
        defaultRequestListeners,
        isLoggingRequestOriginsEnabled);
  }

可以看到,在创建glide对象时,会创建 RequestManagerRetriever对象,返回回去,再去调用RequestManager的get()方法,这个方法也挺重要,一起分析下

代码语言:txt
复制
public RequestManager get(@NonNull FragmentActivity activity) {
    //区分在哪个线程中执行的
    if (Util.isOnBackgroundThread()) {
      return get(activity.getApplicationContext());
    } else {
      assertNotDestroyed(activity);
      //拿到fragment的管理者
      FragmentManager fm = activity.getSupportFragmentManager();
      return supportFragmentGet(
          activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
    }
  }
  
  private RequestManager supportFragmentGet(
      @NonNull Context context,
      @NonNull FragmentManager fm,
      @Nullable Fragment parentHint,
      boolean isParentVisible) {
      // 1.从activity中获取requestManager,用于监管activity的生命周期
    SupportRequestManagerFragment current =
        getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
      // 2.获取当前页面中的请求管理器requestManager
    RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
      Glide glide = Glide.get(context);
      // 3.不存在就创建一个,保存在 SupportRequestManagerFragment 中
      requestManager =
          factory.build(
              glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
      current.setRequestManager(requestManager);
    }
    return requestManager;
  }
  
  private SupportRequestManagerFragment getSupportRequestManagerFragment(
      @NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
      // 2.1通过Tag拿到 RequestManagerFragment,第一次应该是空
    SupportRequestManagerFragment current =
        (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
    if (current == null) {
    // 2.2 如果为空,就从HasMap中取
      current = pendingSupportRequestManagerFragments.get(fm);
      if (current == null) {
      // 2.3还为空 就创建一个
        current = new SupportRequestManagerFragment();
        current.setParentFragmentHint(parentHint);
        if (isParentVisible) {
          current.getGlideLifecycle().onStart();
        }
        // 2.4添加到缓存中
        pendingSupportRequestManagerFragments.put(fm, current);
        fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
        //2.5添加成功,移除缓存
        handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
      }
    }
    //返回requestManage
    return current;
  }

  // 2.2.1 是一个HasMap
  final Map<FragmentManager, SupportRequestManagerFragment> pendingSupportRequestManagerFragments =
      new HashMap<>();

with()总结

可以看出Glide.with()方法主要做了两件事,1.创建glide对象 2.获取到当前界面的生命周期。获取到glide对象很好理解,为何要获取当前界面的生命周期呢?我们都知道图片加载的速度慢于界面加载的速度,通过界面的生命周期,我们就能控制glide是否要继续加载未加载完的图片等,稍后还要继续分析。

2. Glide.load()

代码语言:txt
复制
RequestManage.java

 public RequestBuilder<Drawable> load(@Nullable String string) {
    return asDrawable().load(string);
  }
 public RequestBuilder<Drawable> asDrawable() {
    return as(Drawable.class);
  }
  //参数是 Drawable类型
   public <ResourceType> RequestBuilder<ResourceType> as(
      @NonNull Class<ResourceType> resourceClass) {
      //创建了一个RequestBuilder
      //this指代RequestManage
    return new RequestBuilder<>(glide, this, resourceClass, context);
  }
代码语言:txt
复制
RequestBuilder.java

 protected RequestBuilder(
      @NonNull Glide glide,
      RequestManager requestManager,
      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();

    //为requestBuild 添加监听
    initRequestListeners(requestManager.getDefaultRequestListeners());
    //设置默认RequestOption
    apply(requestManager.getDefaultRequestOptions());
  }
  
   public T apply(@NonNull BaseRequestOptions<?> o) {
    if (isAutoCloneEnabled) {
      return clone().apply(o);
    }
    BaseRequestOptions<?> other = o;

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

    // Applying options with dontTransform() is expected to clear our transformations.
    if (!isTransformationAllowed) {
      transformations.clear();
      fields &= ~TRANSFORMATION;
      isTransformationRequired = false;
      fields &= ~TRANSFORMATION_REQUIRED;
      isScaleOnlyOrNoTransform = true;
    }

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

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

load()总结

load主要做了那些事情呢?1.构建了RequestBuilder2.initRequestListeners添加监听3.设置默认的RequestOption,4.设置加载图片的地址

3. Glide.into()

代码语言:txt
复制
 public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
   //requestBuild继承了BaseRequestOptions
    BaseRequestOptions<?> requestOptions = this;
    if (!requestOptions.isTransformationSet()
        && requestOptions.isTransformationAllowed()
        //缩放的类型不是null
        && view.getScaleType() != null) {
        // View's缩放类型
      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(
        //创建一个viewTarget
        glideContext.buildImageViewTarget(view, transcodeClass),
        null,
        requestOptions,
        Executors.mainThreadExecutor());
  }
代码语言:txt
复制
 public <X> ViewTarget<ImageView, X> buildImageViewTarget(
      @NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {
      //通过target工厂类创建target,transcodeClass 是Drawable.class
    return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
  }
  
  public <Z> ViewTarget<ImageView, Z> buildTarget(@NonNull ImageView view,
      @NonNull Class<Z> clazz) {
      // 当前传入的clazz 是 Drawable.class
    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)");
    }
  }
  最终返回一个DrawableImageViewTarget
代码语言:txt
复制
  //接下来继续走 into() 方法
  private <Y extends Target<TranscodeType>> Y into(
      @NonNull Y target,
      @Nullable RequestListener<TranscodeType> targetListener,
      BaseRequestOptions<?> options,
      Executor callbackExecutor) {
    Preconditions.checkNotNull(target);
    // isModelSet 在load()时设置了isModelSet=true;
    if (!isModelSet) {
      throw new IllegalArgumentException("You must call #load() before calling #into()");
    }
    //根据当前传入的 target,option 创建一个请求
    Request request = buildRequest(target, targetListener, options, callbackExecutor);
    //从当前target中获取request
    Request previous = target.getRequest();
    // isEquivalentTo 是用来判断新创建的request是否是已经创建了的previous,意思是此target// 是否已经创建过了request,避免重复创建;isSkipMemoryCacheWithCompletePreviousReque// st方法是判断此request是否正在请求中或是请求已经完成
    if (request.isEquivalentTo(previous)
        && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
       // 满足以上两个条件,那么刚创建的request可以回收了
      request.recycle();
      if (!Preconditions.checkNotNull(previous).isRunning()) {
        // Use the previous request rather than the new one to allow for optimizations like skipping
        // setting placeholders, tracking and un-tracking Targets, and obtaining View dimensions
        // that are done in the individual Request.
        previous.begin();
      }
      return target;
    }
    //清空target的任何请求
    requestManager.clear(target);
    //给target 设置请求
    target.setRequest(request);
    //requestManager 分发任务
    requestManager.track(target, request);

    return target;
  }
  
  synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
    // 将target放入set集合中
    targetTracker.track(target);
    //准备请求
    requestTracker.runRequest(request);
  }
  
    private final Set<Request> requests =
      Collections.newSetFromMap(new WeakHashMap<Request, Boolean>());
      
   public void runRequest(@NonNull Request request) {
    //将请求加入set集合中
    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);
    }
  }
  
  public final class SingleRequest<R> implements Request,
    SizeReadyCallback,
    ResourceCallback,
    FactoryPools.Poolable {
    
  @Override
  public synchronized void begin() {
    //modle是传入的url
    if (model == null) {
      if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
        width = overrideWidth;
        height = overrideHeight;
      }
      onLoadFailed(new GlideException("Received null model"), logLevel);
      return;
    }
    //判断当前的状态  正在加载中
    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)) {
     //表示尺寸已经准备好了
      onSizeReady(overrideWidth, overrideHeight);
    } else {
      target.getSize(this);
    }
  }
  
   @Override
  public synchronized void onSizeReady(int width, int height) {
  //  调用了 Engine.load 方法构建任务
   loadStatus = engine.load(glideContext,model.....);
  
  }
    
    
    }

可以看到 onSizeReady 去构建可执行任务, 接下来我们就分析这一过程。

代码语言:txt
复制
public class Engine implements EngineJobListener,
    MemoryCache.ResourceRemovedListener,
    EngineResource.ResourceListener {
    
    public synchronized <R> LoadStatus load(....) {
    //1.通过传入的参数构建一个EngineKey
    EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations,
        resourceClass, transcodeClass, options);
    // 2. 从缓存中查找 key 对应的资源
    // 2.1 尝试从 ActiveResources 缓存中查找这个 key 的缓存(内存缓存)
    EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
    if (active != null) {
    // 若缓存存在, 则直接回调 onResourceReady 处理后续操作
      cb.onResourceReady(active, DataSource.MEMORY_CACHE);
      return null;
    }
    // 2.2 尝试从 LruResourceCache 中找寻这个资源 
    EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
    if (cached != null) {
      cb.onResourceReady(cached, DataSource.MEMORY_CACHE);
      return null;
    }
    // 3. 尝试从 请求任务 中找寻这个资源 
    EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
    if (current != null) {
    // 3.1 走到这里说明这个任务已经正在执行了, 无需再次构建执行
      current.addCallback(cb, callbackExecutor);
    //返回一个LoadStatus状态
      return new LoadStatus(cb, current);
    }
    // 3.2 走到这里, 说明是一个新的任务
    // 3.2.1 则构建一个新的引擎任务
    EngineJob<R> engineJob = engineJobFactory.build(...);
     // 3.2.2 构建解码任务
    DecodeJob<R> decodeJob = decodeJobFactory.build(...);
    // 3.2.3 添加到任务缓存,防止多次构建
    jobs.put(key, engineJob);
    ...
     // 3.2.4 执行任务
    engineJob.start(decodeJob);
    //返回一个LoadStatus状态
    return new LoadStatus(cb, engineJob);
  }
    }

可以看出Engine.load()方法做了几件重要的事

  • 构建一个EngineKey,从缓存中查找,如果找到了,则返回缓存中的数据 1.从ActiveResources缓存中查找key的缓存 2.从LruResourceCache 缓存中查找key的缓存
  • 从请求任务中 查找key的缓存 engineJobFactory() decodeJobFactory() jobs.put()
  • 没有找到则添加一个新的任务,并执行任务,返回此时的加载状态

好的, 可以看到内存缓存的处理是在 Engine 中进行的, 若两个内存缓存都没有命中, 则会构建任务并执行, 接下来我们看看任务的执行过程

代码语言:txt
复制
public synchronized void start(DecodeJob<R> decodeJob) {
    this.decodeJob = decodeJob;
    //获取执行的线程池
    GlideExecutor executor = decodeJob.willDecodeFromCache()
        ? diskCacheExecutor
        : getActiveSourceExecutor();
    // 执行任务
    executor.execute(decodeJob);
  }
  
  class DecodeJob<R> implements DataFetcherGenerator.FetcherReadyCallback,
    Runnable,
    Comparable<DecodeJob<?>>,
    Poolable {
    
     @Override
  public void run() {
    try {
      ...
      // 调用了 runWrapped
      runWrapped();
      ...
    } 
  }
  
  private void runWrapped() {
    switch (runReason) {
      case INITIALIZE:
        // 1. 获取任务的场景
        stage = getNextStage(Stage.INITIALIZE);
        // 2. 获取这个场景的执行者
        currentGenerator = getNextGenerator();
        // 3. 执行者执行任务
        runGenerators();
        break;
      case SWITCH_TO_SOURCE_SERVICE:
        runGenerators();
        break;
      case DECODE_DATA:
        decodeFromRetrievedData();
        break;
      default:
        throw new IllegalStateException("Unrecognized run reason: " + runReason);
    }
  }
  
  private Stage getNextStage(Stage current) {
    switch (current) {
      case INITIALIZE:
      // 1.1 若我们配置的缓存策略允许从 资源缓存 中读数据, 则返回 Stage.RESOURCE_CACHE
        return diskCacheStrategy.decodeCachedResource()
            ? Stage.RESOURCE_CACHE : getNextStage(Stage.RESOURCE_CACHE);
      case RESOURCE_CACHE:
      // 1.2 若我们配置的缓存策略允许从 源数据缓存中读数据, 则返回 Stage.DATA_CACHE
        return diskCacheStrategy.decodeCachedData()
            ? Stage.DATA_CACHE : getNextStage(Stage.DATA_CACHE);
      case DATA_CACHE:
      // 1.3 若只能允许从缓存中获取数据, 则直接 FINISH, 否则返回 Stage.SOURCE, 意为加载一个新的资源
        return onlyRetrieveFromCache ? Stage.FINISHED : Stage.SOURCE;
      case SOURCE:
      case FINISHED:
        return Stage.FINISHED;
      default:
        throw new IllegalArgumentException("Unrecognized stage: " + current);
    }
  }
  
  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);
    }
  }
  
  private void runGenerators() {
   // 调用 DataFetcherGenerator.startNext() 执行了请求操作
    while (!isCancelled && currentGenerator != null
        && !(isStarted = currentGenerator.startNext())) {
      stage = getNextStage(stage);
      currentGenerator = getNextGenerator();

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

DecodeJob 任务执行时, 它根据不同的场景, 获取不同的场景执行器, 然后调用了它们的 startNext 方法加载请求任务的数据, 其映射表为

场景

场景描述

场景执行器

Stage.RESOURCE_CACHE

从磁盘中缓存的资源中获取数据

ResourceCacheGenerator

Stage.DATA_CACHE

从磁盘中缓存的源数据中获取数据

DataCacheGenerator

Stage.SOURCE

重新请求数据

SourceGenerator

我们知道在 Engine 中, 尝试从内存缓存中获取资源, 而 DecodeJob 则是尝试从磁盘缓存中获取资源, 我们这里主要查看 SourceGenerator.startNext 是如何加载请求任务的数据的

代码语言:txt
复制
class SourceGenerator implements DataFetcherGenerator,
    DataFetcher.DataCallback<Object>,
    DataFetcherGenerator.FetcherReadyCallback {
   @Override
    public boolean startNext() {
      ...
      loadData = null;
      boolean started = false;
      while (!started && hasNextModelLoader()) {
      // 1. 从 DecodeHelper 的数据加载集合中, 获取一个数据加载器
        loadData = helper.getLoadData().get(loadDataListIndex++);
        if (loadData != null
            && (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
            || helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
          started = true;
          // 2. 使用加载器中 fetcher 执行数据加载
          loadData.fetcher.loadData(helper.getPriority(), this);
        }
      }
      return started;
    }
}

可以看出SourceGenerator主要有两步

  • 调用 DecodeHelper.getLoadData 获取当前请求的数据加载器
  • 调用加载器中的 fetcher.loadData 真正的执行数据加载

1.获取数据加载器

代码语言:txt
复制
final class DecodeHelper<Transcode> {
  List<LoadData<?>> getLoadData() {
    if (!isLoadDataSet) {
      isLoadDataSet = true;
      loadData.clear();
      // 1. 从 Glide 注册的 register 中获取请求 model 加载器
      List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model);
      // 遍历每一个 modelLoaders 
      for (int i = 0, size = modelLoaders.size(); i < size; i++) {
        ModelLoader<Object, ?> modelLoader = modelLoaders.get(i);
        //通过传入的参数获取 loadData
        LoadData<?> current =
            modelLoader.buildLoadData(model, width, height, options);
        if (current != null) {
          loadData.add(current);
        }
      }
    }
    return loadData;
  }
}

它会找到一个 ModelLoader 的实现类, 通过这个实现类的 handles 方法, 判断是否可以加载这个 model

这里我们的 model 以网络的 URL 资源举例, 它的实现类为 HttpGlideUrlLoader 我们看看它如何构建一个 LoadData 对象的

代码语言:txt
复制
public class HttpGlideUrlLoader implements ModelLoader<GlideUrl, InputStream> {  
  @Override
  public LoadData<InputStream> buildLoadData(@NonNull GlideUrl model, int width, int height, @NonNull Options options) {
    GlideUrl url = model;
    ...
    int timeout = options.get(TIMEOUT);
    // 创建了一个 LoadData 对象, 并且实例化了一个 HttpUrlFetcher 给它
    return new LoadData<>(url, new HttpUrlFetcher(url, timeout));
  }
}

好的, 可以看到对于 URL 的加载, 其 fetcher 为一个 HttpUrlFetcher 的实例, 接下来我们看看数据加载的流程

1.执行数据加载

代码语言:txt
复制
public class HttpUrlFetcher implements DataFetcher<InputStream> {
   @Override
  public void loadData(@NonNull Priority priority,
      @NonNull DataCallback<? super InputStream> callback) {
    long startTime = LogTime.getLogTime();
    try {
      //发起请求,获得InputStream
      InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
      //回掉结果
      callback.onDataReady(result);
    } catch (IOException e) {
      //出现异常
      callback.onLoadFailed(e);
    } 
  }
}

接下来看看urlConnection的请求

代码语言:txt
复制
public class HttpUrlFetcher implements DataFetcher<InputStream> {
  private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl,
      Map<String, String> headers) throws IOException {
    // 1.构建一个 urlConnection
    urlConnection = connectionFactory.build(url);
    // 2.设置head头
    for (Map.Entry<String, String> headerEntry : headers.entrySet()) {
      urlConnection.addRequestProperty(headerEntry.getKey(), headerEntry.getValue());
    }
    ...
    // 3.是否进行重定向
    urlConnection.setInstanceFollowRedirects(false);
    // 4.发起请求
    urlConnection.connect();
    // 拿到inputstrean
    stream = urlConnection.getInputStream();
    if (isCancelled) {
      return null;
    }
    final int statusCode = urlConnection.getResponseCode();
    if (isHttpOk(statusCode)) {
      // statusCode==200
      return getStreamForSuccessfulRequest(urlConnection);
    } else if (isHttpRedirect(statusCode)) {
      // statusCode==300
     ...
      return loadDataWithRedirects(redirectUrl, redirects + 1, url, headers);
    } else if (statusCode == INVALID_STATUS_CODE) {
      throw new HttpException(statusCode);
    } else {
      throw new HttpException(urlConnection.getResponseMessage(), statusCode);
    }
  }
}

可以看到glide使用 urlConnection 发起网络请求,通过callback回掉结果。接下来看获取到数据后是如果处理的

处理数据源

代码语言:txt
复制
class DecodeJob<R> implements DataFetcherGenerator.FetcherReadyCallback,
    Runnable,Comparable<DecodeJob<?>>,Poolable {
    
    @Override
    public void onDataFetcherReady(Key sourceKey, Object data, DataFetcher<?> fetcher,
        DataSource dataSource, Key attemptedKey) {
      this.currentSourceKey = sourceKey; // 保存数据的 key
      this.currentData = data;          // 保存数据实体
      this.currentFetcher = fetcher;    // 保存数据的获取器
      this.currentDataSource = dataSource;// 数据来源: url 为 REMOTE 类型的枚举, 表示从远程获取
      ...
      if (Thread.currentThread() != currentThread) {
       ...
      } else {
  
        try {
        // 1. 调用了 decodeFromData 获取资源
          decodeFromRetrievedData();
        } finally {
          GlideTrace.endSection();
        }
      }
    }
  }
  
    private void decodeFromRetrievedData() {
    ...
    Resource<R> resource = null;
    try {
      // 1.解析资源
      resource = decodeFromData(currentFetcher, currentData, currentDataSource);
    } catch (GlideException e) {
      e.setLoggingDetails(currentAttemptingKey, currentDataSource);
      throwables.add(e);
    }
    if (resource != null) {
      // 2.通知外界获取到资源
      notifyEncodeAndRelease(resource, currentDataSource);
    } else {
      runGenerators();
    }
  }

可以看到对于获取到的数据, 首先要将其解码为 Resource 类型的资源, 然后再将资源返回给上层

我们先看看它是如何将数据解析成 Resource(非 Android 系统的 Resource) 资源的

代码语言:txt
复制
class DecodeJob<R> implements DataFetcherGenerator.FetcherReadyCallback,
    Runnable,Comparable<DecodeJob<?>>,Poolable {
    
    private <Data> Resource<R> decodeFromData(DataFetcher<?> fetcher, Data data,
      DataSource dataSource) throws GlideException {
    try {
    ...
    //调用了decodeFromFetcher
      Resource<R> result = decodeFromFetcher(data, dataSource);
      return result;
    } finally {
      fetcher.cleanup();
    }
  }
}

  
  private <Data> Resource<R> decodeFromFetcher(Data data, DataSource dataSource)
      throws GlideException {
      // 1. 获取当前数据类的解析器 LoadPath
    LoadPath<Data, ?, R> path = decodeHelper.getLoadPath((Class<Data>) data.getClass());
    // 2. 通过解析器来解析来解析数据
    return runLoadPath(data, dataSource, path);
  }
  
   private <Data, ResourceType> Resource<R> runLoadPath(Data data, DataSource dataSource,
      LoadPath<Data, ResourceType, R> path) throws GlideException {
    Options options = getOptionsWithHardwareConfig(dataSource);
    // 2.1 根据数据类型获取一个数据重造器, 获取的数据为 InputStream, 因此它是一个 InputStreamRewinder 的实例
    DataRewinder<Data> rewinder = glideContext.getRegistry().getRewinder(data);
    try {
       // 2.2 将解析资源的任务转移到了 LoadPath.load 方法中
      return path.load(
          rewinder, options, width, height, new DecodeCallback<ResourceType>(dataSource));
    } finally {
      rewinder.cleanup();
    }
  }

可以看到为了解析数据, 首先构建了一个 LoadPath, 然后创建了一个 InputStreamRewinder 类型的 DataRewinder, 最终将数据解析的操作到了 LoadPath.load 方法中

接下来看看这个LoadPath.load 做了哪些处理

代码语言:txt
复制
public class LoadPath<Data, ResourceType, Transcode> {

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

 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 {
        result = path.decode(rewinder, width, height, options, decodeCallback);
      } catch (GlideException e) {
        exceptions.add(e);
      }
      ...
    return result;
  }
  
public class DecodePath<DataType, ResourceType, Transcode> {
   public Resource<Transcode> decode(DataRewinder<DataType> rewinder, int width, int height,
      @NonNull Options options, DecodeCallback<ResourceType> callback) throws GlideException {
        // 1. 调用 decodeResource 将源数据解析成中间资源
    Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);
     // 2. 调用 DecodeCallback.onResourceDecoded 处理中间资源
    Resource<ResourceType> transformed = callback.onResourceDecoded(decoded);
     // 3. 调用 ResourceTranscoder.transcode 将中间资源转为目标资源
    return transcoder.transcode(transformed, options);
  }
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. Glide.with()
    • 1.1 获取 RequestManagerRetriever 对象
      • with()总结
      • 2. Glide.load()
        • load()总结
          • 1.获取数据加载器
          • 1.执行数据加载
          • 处理数据源
      • 3. Glide.into()
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档