glide流程梳理

glide现在已经4.x了, 就以该版本的源码进行分析了.

glide优势

  • 通过Fragment来监听页面生命周期来控制图片的加载与取消;
  • 使用@GlideModel的方式可动态注册、替换图片加载器;
  • glide初始化时注册加载器、转码器、编码器等;
  • Target通过ViewTreeObserver来监听控件的宽高提供给BitmapFactory.decodeStream()来解码原始流;
  • 四级缓存, 活跃缓存、内存缓存、硬盘缓存、网络加载;
  • 可以返回多种数据格式Drawable、Bitmap.

Glide.with(this)

initializeGlide()

解码资源的接口(如将File, InputStream etc 解码为Bitmap, Drawable etc):  public interface ResourceDecoder<T, Z> ;

将数据编码写入持久性数据存储区(如本地文件缓存)的接口: public interface Encoder<T> ;

将一种类型的资源转码为另一种类型的资源(如Resources转BitmapDrawable): public interface ResourceTranscoder<Z, R>  ;

将任意复杂的数据模型转换为具体的数据类型的工厂接口(如请求网络获取原始流): public interface ModelLoader<Model, Data>;

  • encoderRegistry.append(dataClass, encoder);            数据编码存储注册
  • decoderRegistry.append(bucket/**解码器的存储桶标识符*/, decoder/**已注册的ResourceDecoder*/, dataClass/**被解码的数据(比如流)*/, resourceClass/**解码结果数据(比如Bitmap)*/);  解码器注册
  • modelLoaderRegistry.append(modelClass/**模型类(如URL, file path)*/, dataClass/**返回的数据类型(如InputStream)*/, factory/**模型加载工厂类*/);                                                               模型加载器注册
  • transcoderRegistry.register(resourceClass/**将被转码的类型(如Bitmap)*/, transcodeClass/**转码后的类型(如BitmapDrawable)*/, transcoder/**已注册的资源转码器*/);                            转码器注册
  • RequestManagerRetriever.ID_REMOVE_SUPPORT_FRAGMENT_MANAGER 存在的作用???
  • RequestManagerRetriever.supportFragmentGet() 中实现将RequestManager注册到SupportRequestManagerFragment的ActivityFragmentLifecycle属性中来感知Fragment的生命周期来进行图片的加载与取消.
  • 反射获取业务方@GlideModel注解的类;
  • manifest解析
  • 排除manifest下被注解配置的model
  • 引用传递参数给自定义模块

RequestManager.load(url)

 /** 
  * 指定ResourceType为Drawable, transcodeClass为Drawable.class 
  */
 public <ResourceType> RequestBuilder<ResourceType> as(
      @NonNull Class<ResourceType> resourceClass) {
    return new RequestBuilder<>(glide, this, resourceClass, context);
  }


  /**
   * 结合上面方法:load(url)后 model类型为String, transcodeClass为Drawable.class
   */
  public RequestBuilder<Drawable> load(@Nullable String string) {
    return asDrawable().load(string);
  }

生命周期绑定

传入的不同类型的参数Fragment、Activity、Context、Application创建一个没有界面的 RequestManagerFragment , 返回 RequestManager 对象,  为了绑定生命周期将 RequestManagerFragment 的属性 ActivityFragmentLifecycle 传递到 RequestManager, 让 RequestManager 将自己注册到 ActivityFragmentLifecycle 的观察者集合, 从而在 RequestManagerFragment 的生命周期方法中通知事件订阅者. 构造 RequestManager 对象时初始化了 RequestManager.glide 属性 , 此时 glide的属性, 注册不同格式数据源的编码、解码器对象, 不同数据来源的加载器对象, 图片对象变换器, 编码转换器等被初始化.

资源加载器、转换器、编码器、变换器、内存缓存、硬盘缓存、active缓存对象的初始化

    // glide对象的属性
    private Engine engine;
    private BitmapPool bitmapPool;
    private MemoryCache memoryCache;          // LruResourceCache 原数据内存缓存
    private ExecutorService sourceService;    // FIFO 网络请求线程池
    private ExecutorService diskCacheService; // FIFO 磁盘操作线程池
    private DecodeFormat decodeFormat;
    private DiskCache.Factory diskCacheFactory;  // 磁盘操作接口类DiskCache


    // 为 Engine 类的属性, 构造glide对象时初始化glide.engine属性
    private final Map<Key, EngineJob> jobs;
    private final EngineKeyFactory keyFactory;
    private final MemoryCache cache;
    private final EngineJobFactory engineJobFactory;
    private final Map<Key, WeakReference<EngineResource<?>>> activeResources;
    private final ResourceRecycler resourceRecycler;
    private final LazyDiskCacheProvider diskCacheProvider;
RequestManager.load(url)

根据as(Drawable.class)参数类型Drawable.class构建RequestBuilder(Glide glide, RequestManager requestManager, Class<TranscodeType> transcodeClass, Context context)对象,  继续构造this.mode = url; 返回RequestBuilder对象.

RequestBuilder.into(imageView)

转换为

RequestBuilder.into(
        glideContext.buildImageViewTarget(view, transcodeClass),
        /*targetListener=*/ null,
        requestOptions);

其中glideContext是在Glide的构造方法中初始化的,  使用工厂模式根据参数的classType从ImageViewTargetFactory构造一个(ViewTarget<ImageView, Z>)DrawableImageViewTarget对象, 请求类SingleRequest, 请求池类 Pools.Pool<SingleRequest<?>>, 在调用engine.load()传入了this作为回调接口ResourceCallback, 


    requestManager.clear(target);
    target.setRequest(request);
    requestManager.track(target, request);

  void track(@NonNull Target<?> target, @NonNull Request request) {
    targetTracker.track(target);
    requestTracker.runRequest(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);
    }
  }

真正的加载是在Engine.load()中的DecodeJob.run();

  public <R> LoadStatus load(...) {

    EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations,
        resourceClass, transcodeClass, options);
    // 活跃缓存
    EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
    if (active != null) {
      cb.onResourceReady(active, DataSource.MEMORY_CACHE);
      return null;
    }
    // 内存缓存
    EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
    if (cached != null) {
      cb.onResourceReady(cached, DataSource.MEMORY_CACHE);
      return null;
    }

    EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
    if (current != null) {
      current.addCallback(cb);
      return new LoadStatus(cb, current);
    }
    EngineJob<R> engineJob = engineJobFactory.build(...);
    DecodeJob<R> decodeJob = decodeJobFactory.build(..., engineJob);
    jobs.put(key, engineJob);
    engineJob.addCallback(cb);
    engineJob.start(decodeJob);
 }

runWrapped()

  private void runWrapped() {
    switch (runReason) { // 初始化为INITIALIZE
      case INITIALIZE:
        stage = getNextStage(Stage.INITIALIZE); // 递归获取值为 Stage.SOURCE
        currentGenerator = getNextGenerator(); // 返回 new SourceGenerator(decodeHelper, this);
        runGenerators();                       /** 执行SourceGenerator.startNext()下载网络图片 */
        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:
        return diskCacheStrategy.decodeCachedResource()
            ? Stage.RESOURCE_CACHE : getNextStage(Stage.RESOURCE_CACHE);
      case RESOURCE_CACHE:
        return diskCacheStrategy.decodeCachedData()
            ? Stage.DATA_CACHE : getNextStage(Stage.DATA_CACHE);
      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);
    }
  }

 

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

 

加载数据的入口

使用OkHttp加载数据并回调

 @Override
  public void onDataFetcherReady(Key sourceKey, Object data, DataFetcher<?> fetcher,
      DataSource dataSource, Key attemptedKey) {

    if (Thread.currentThread() != currentThread) {
      runReason = RunReason.DECODE_DATA;
      callback.reschedule(this);
    } else {
      GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData");
      try {
        decodeFromRetrievedData();
      } finally {
        GlideTrace.endSection();
      }
    }
  }

解码和转码

  private void decodeFromRetrievedData() {
    Resource<R> resource = null;
    try {
      resource = decodeFromData(currentFetcher, currentData, currentDataSource);
    } catch (GlideException e) {
      e.setLoggingDetails(currentAttemptingKey, currentDataSource);
      throwables.add(e);
    }
    if (resource != null) {
      notifyEncodeAndRelease(resource, currentDataSource);
    } else {
      runGenerators();
    }
  }

从注册的解码器集合中查找能处理原数据的解码器

 

解码

解码变换完成切换线程

String类型的url默认是HttpUrlFetcher.loadData()加载图片, 回调是SourceGenerator.onDataReady()

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

 

从网络加载图片数据OkHttpStreamFetcher

硬盘缓存加载时序图

测试的时候硬盘缓存策略使用的是DiskCacheStrategy.DATA

  public static final DiskCacheStrategy DATA = new DiskCacheStrategy() {
    @Override
    public boolean isDataCacheable(DataSource dataSource) {
      return dataSource != DataSource.DATA_DISK_CACHE && dataSource != DataSource.MEMORY_CACHE;
    }

    @Override
    public boolean isResourceCacheable(boolean isFromAlternateCacheKey, DataSource dataSource,
        EncodeStrategy encodeStrategy) {
      return false;
    }

    @Override
    public boolean decodeCachedResource() {
      return false;
    }

    @Override
    public boolean decodeCachedData() {
      return true;
    }
  };
  private Stage getNextStage(Stage current) {
    switch (current) {
      case INITIALIZE:
        return diskCacheStrategy.decodeCachedResource()
            ? Stage.RESOURCE_CACHE : getNextStage(Stage.RESOURCE_CACHE);
      case RESOURCE_CACHE:
        return diskCacheStrategy.decodeCachedData()
            ? Stage.DATA_CACHE : getNextStage(Stage.DATA_CACHE);
      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);
    }
  }

 

解转码流程

缓存相关类

硬盘缓存相关类:  DiskLruCacheFactory、 DiskLruCacheWrapper、InternalCacheDiskCacheFactory

硬盘缓存读取  DiskLruCacheWrapper.get() 的调用方: 

DataCacheGenerator.startNext() 尝试先从磁盘缓存中读取, 未获取到再从网络读取;

ResourceCacheGenerator.startNext() 尝试先从磁盘缓存中读取, 未获取到再从网络读取.

硬盘缓存存储  DiskLruCacheWrapper.put() 的调用方: 

DecodeJo$DeferredEncodeManager.encode()存储到硬盘

内存缓存相关类: LruResourceCache、ActiveResources

ActiveResources.activate()的调用方:

Engine.load()  -> Engine.loadFromCache() ;

Engine.onEngineJobComplete().

ActiveResources.get()的调用方:

Engine.load()  -> Engine.loadFromActiveResources()

ActiveResources.deactivate()的调用方:

Engine.onResourceReleased()

LruResourceCache.remove()的调用方:

Engine.load() -> Engine.loadFromCache() -> Engine.getEngineResourceFromCache()

LruResourceCache.put()的调用方:

Engine.onResourceReleased();

Engine.cache.setResourceRemovedListener(Engine.this);

BitmapPool相关类: LruBitmapPool

变化工具类: TransformationUtils

 

SimpleTarget的使用追踪

DownsampleStrategy内置了几个DownsampleStrategy.CenterOutside

    // sourceWidth     服务器端返回的图片宽度
    // requestedWidth  UI控件的宽度
    // 返回缩放百分比的较大值
    public float getScaleFactor(int sourceWidth, int sourceHeight, int requestedWidth,
        int requestedHeight) {
      float widthPercentage = requestedWidth / (float) sourceWidth;
      float heightPercentage = requestedHeight / (float) sourceHeight;
      return Math.max(widthPercentage, heightPercentage);
    }

关键问题代码

  int targetWidth = requestedWidth == Target.SIZE_ORIGINAL ? sourceWidth : requestedWidth;
  int targetHeight = requestedHeight == Target.SIZE_ORIGINAL ? sourceHeight : requestedHeight;

具体的缩放因子与ImageView控件的scaleType有关, 参考类DownsampleStrategy

options.inTargetDensity > 0 && options.inDensity 

Glide.with(MainActivity.this)
        .load(url)
        .into(imageView);

分析一下调用后此处图片的宽高和控件的宽高:

RequestBuilder.into()中通过工厂类ImageViewTargetFactory.buildTarget()获取DrawableImageViewTarget对象;

执行SingleRequest.begin()的   

if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
    onSizeReady(overrideWidth, overrideHeight);
} else {
    target.getSize(this);
}

调用的是ViewTarget.getSize(), 其实是调用的ViewTarget$SizeDeterminer.getSize(),核心是     

 if (layoutListener == null) {
     ViewTreeObserver observer = view.getViewTreeObserver();
     layoutListener = new SizeDeterminerLayoutListener(this);
     observer.addOnPreDrawListener(layoutListener);
 }

private static final class SizeDeterminerLayoutListener
        implements ViewTreeObserver.OnPreDrawListener {
      private final WeakReference<SizeDeterminer> sizeDeterminerRef;

      SizeDeterminerLayoutListener(@NonNull SizeDeterminer sizeDeterminer) {
        sizeDeterminerRef = new WeakReference<>(sizeDeterminer);
      }

      @Override
      public boolean onPreDraw() {
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
          Log.v(TAG, "OnGlobalLayoutListener called attachStateListener=" + this);
        }
        SizeDeterminer sizeDeterminer = sizeDeterminerRef.get();
        if (sizeDeterminer != null) {
          sizeDeterminer.checkCurrentDimens();
        }
        return true;
      }
}

再回到SingleRequest.onSizeReady()继续执行. 到执行InputStream解码的时候, 会根据控件的scaleType、宽高和返回的图片流数据中的宽高做缩放, 使用了Option.inSample属性.

 

下次分析:

每次图片加载都new 一个Engine?

 

参考文档 

官网介绍: http://bumptech.github.io/glide/doc/transformations.html

详细blog: https://blog.csdn.net/yanfeivip8/article/details/50418064

郭霖blog: https://blog.csdn.net/guolin_blog/article/details/53759439

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值