Glide源码解析

Glide 源码解析



如果想看 Glide缓存机制的话, 点击这里

当源码量大难懂的时候,看源码的思路:

  1. 只管主线,不管支线,不管支线,不管支线!(这次只看主线)
  2. 重点在主线,稍微瞄一眼支线。
  3. 稍微分析支线,回顾主线。
  4. 分析支线细节,回顾主线。
  5. 分析支线细节,寻找答案。

本次解析是基于Glide-4.11.0版本。

Glide.with(this).load(url).into(imageView).
  • with 创建一个空白的Fragment,来管理生命周期。

  • load 创建一个RequestBuilder对象。

  • into 主要做了一下功能:

  1. 运行队列,等待队列
  2. 活动缓存
  3. 内存缓存
  4. 网络模型

Glide的核心是:生命周期,缓存机制

Glide流程简化图

Glide流程简化图

问题
  1. 为什么去监听生命周期?

答:方便资源的及时回收。

  1. 项目中大量使用Glide 时,偶尔会出现内存泄漏的问题,大概是什么原因?

答:在用with的时候,尽量使用非application作用域,才能进行生命周期的监听,及时回收及释放等操作。

  1. Glide.with()在子线程加载时有什么问题?

答:不会添加空fragment监听生命周期,主线程才会添加。

  1. Glide的缓存为什么要有活动缓存和内存缓存?

答:活动缓存:页面正在显示的图片,必须访问的。内存缓存LRU机制。都是运行时缓存。

如果页面在显示内存里的缓存图片,但这时LRU机制删除了这个缓存,彻底释放资源,就会报错。

所以制定了活动缓存,来存放页面必须用到的缓存。如果用到的缓存在内存缓存则会先移动到活动缓存中。

如果页面关闭掉,活动缓存中数据会再次移动到内存缓存中,等待下次使用。

with

子线程:application作用域,不会创建空白的Fragment

主线程:非application作用域,会创建空白的Fragment

绑定Fragment的时候,第一层判定会先从栈中通过TAG获取是否有fragmentmapfragment进行缓存作为第二层判定。

@NonNull
  private SupportRequestManagerFragment getSupportRequestManagerFragment(
      @NonNull final FragmentManager fm, 
      @Nullable Fragment parentHint, 
      boolean isParentVisible) {
    
    SupportRequestManagerFragment current =
        (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
    // 第一层判定
    if (current == null) {
      current = pendingSupportRequestManagerFragments.get(fm);
      // 第二次判定
      if (current == null) {
        current = new SupportRequestManagerFragment();
        current.setParentFragmentHint(parentHint);
        if (isParentVisible) {
          current.getGlideLifecycle().onStart();
        }
        // 放入集合
        pendingSupportRequestManagerFragments.put(fm, current);
        fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
        /*发送handler通知移除集合,因为fragment的commit就是通过handler执行,
          当handleMessage接收到移除集合的消息,说明fragment commit已经执行了。
          并且避免了内存泄漏。
        */
        handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER,fm).sendToTarget();
      }
    }
    return current;
  }

lifecycle (add,remove LifecycleListener)–>ApplicationLifecycle(绑定Application生命周期),ActivityFragmentLifecycle(绑定空白Fragment生命周期)

RequestManager 实现LifecycleListener接口,去通知其他类生命周期的改变。

public class RequestManager implements LifeCycleListener{
  
  /**
  * 开始所有任务
  * 运行队列全部开始执行,等待队列全部清空
  */
  @Override
  public synchronized void onStart() {
    resumeRequests();
    targetTracker.onStart();
  }

  /**
   * 暂停所有任务
   * 运行队列全部停止,把任务转移到等待队列
   */
  @Override
  public synchronized void onStop() {
    pauseRequests();
    targetTracker.onStop();
  }

  /**
   * 清空所有任务
   */
  @Override
  public synchronized void onDestroy() {
    targetTracker.onDestroy();
    for (Target<?> target : targetTracker.getAll()) {
      clear(target);
    }
    targetTracker.clear();
    requestTracker.clearRequests();
    lifecycle.removeListener(this);
    lifecycle.removeListener(connectivityMonitor);
    mainHandler.removeCallbacks(addSelfToLifecycle);
    glide.unregisterRequestManager(this);
  }
}
Load

主要返回一个 RequestBuilder 对象。待完善…

into

主线大致流程:

  1. ImageViewTarget(显示图片), 无论走多远,一定回到这里。
@NonNull
  public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
    Util.assertMainThread();
    Preconditions.checkNotNull(view);
    // 省略...
		
    return into(
      // 构建ImageViewTarget对象
        glideContext.buildImageViewTarget(view, transcodeClass),
        /*targetListener=*/ null,
        requestOptions,
        Executors.mainThreadExecutor());
  }

在上面的returninto方法中,会有下面的代码:

Request request = buildRequest(target, targetListener, options, callbackExecutor);

buildRequest最终创建的是SingleRequest。这里面层级很深。这里只展示最终创建SingleRequest的地方。

  private Request obtainRequest(
      Target<TranscodeType> target,
      RequestListener<TranscodeType> targetListener,
      BaseRequestOptions<?> requestOptions,
      RequestCoordinator requestCoordinator,
      TransitionOptions<?, ? super TranscodeType> transitionOptions,
      Priority priority,
      int overrideWidth,
      int overrideHeight,
      Executor callbackExecutor) {
    // 享元设计模式
    return SingleRequest.obtain(
        context,
        glideContext,
        model,
        transcodeClass,
        requestOptions,
        overrideWidth,
        overrideHeight,
        priority,
        target,
        targetListener,
        requestListeners,
        requestCoordinator,
        glideContext.getEngine(),
        transitionOptions.getTransitionFactory(),
        callbackExecutor);
  }
  1. 经过requestManager.track()–>requestTracker.runRequest(request)–>request.begin()–>Request的实现类SingleRequest.begin()方法。在begin()方法中,会有下面的判断:
// 用户是否设置了宽和高
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
   onSizeReady(overrideWidth, overrideHeight); // 设置了宽高
} else {
  // 用户没有设置宽和高,会再次测量-->再次调用onSizeReady
   target.getSize(this);
}
  1. onSizeReady()–>engine.load()load里面会有加载缓存的判断:
public <R> LoadStatus load(
      GlideContext glideContext,
      Object model,
      Key signature,
      int width,
      int height,
      Class<?> resourceClass,
      Class<R> transcodeClass,
      Priority priority,
      DiskCacheStrategy diskCacheStrategy,
      Map<Class<?>, Transformation<?>> transformations,
      boolean isTransformationRequired,
      boolean isScaleOnlyOrNoTransform,
      Options options,
      boolean isMemoryCacheable,
      boolean useUnlimitedSourceExecutorPool,
      boolean useAnimationPool,
      boolean onlyRetrieveFromCache,
      ResourceCallback cb,
      Executor callbackExecutor) {
    long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0;
// 1.构建key
    EngineKey key =
        keyFactory.buildKey(
            model,
            signature,
            width,
            height,
            transformations,
            resourceClass,
            transcodeClass,
            options);

    EngineResource<?> memoryResource;
    synchronized (this) {
      // 2.loadFromMemory会先后从 活动缓存和内存缓存 获取缓存
      memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);

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

其中,活动缓存:页面正在显示的图片,必须访问的。内存缓存:LRU机制。(这里不详细说了)

5.waitForExistingOrStartNewJob()方法中会有

  private <R> LoadStatus waitForExistingOrStartNewJob(
      GlideContext glideContext,
      Object model,
      Key signature,
      int width,
      int height,
      Class<?> resourceClass,
      Class<R> transcodeClass,
      Priority priority,
      DiskCacheStrategy diskCacheStrategy,
      Map<Class<?>, Transformation<?>> transformations,
      boolean isTransformationRequired,
      boolean isScaleOnlyOrNoTransform,
      Options options,
      boolean isMemoryCacheable,
      boolean useUnlimitedSourceExecutorPool,
      boolean useAnimationPool,
      boolean onlyRetrieveFromCache,
      ResourceCallback cb,
      Executor callbackExecutor,
      EngineKey key,
      long startTime) {
// 1.是否有正在运行的任务
    EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
    if (current != null) {
      current.addCallback(cb, callbackExecutor);
      if (VERBOSE_IS_LOGGABLE) {
        logWithTimeAndKey("Added to existing load", startTime, key);
      }
      return new LoadStatus(cb, current);
    }
// 1.EngineJob是线程池大管家
    EngineJob<R> engineJob =
        engineJobFactory.build(
            key,
            isMemoryCacheable,
            useUnlimitedSourceExecutorPool,
            useAnimationPool,
            onlyRetrieveFromCache);
// 2.执行的任务
    DecodeJob<R> decodeJob =
        decodeJobFactory.build(
            glideContext,
            model,
            key,
            signature,
            width,
            height,
            resourceClass,
            transcodeClass,
            priority,
            diskCacheStrategy,
            transformations,
            isTransformationRequired,
            isScaleOnlyOrNoTransform,
            onlyRetrieveFromCache,
            options,
            engineJob);

    jobs.put(key, engineJob);

    engineJob.addCallback(cb, callbackExecutor);
    engineJob.start(decodeJob);

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

  1. engineJob.start(decodeJob)会执行 decodeJob中的run方法,run()-->runWrapped()-->getNextGenerator()默认会返回SourceGenerator–>runGenerators()–>SourceGenerator .startNext()–>helper.getLoadData() {–>modelLoader.buildLoadData()–>HttpGlideUrlLoader.buildLoadData()–>new LoadData<>(url, new HttpUrlFetcher(url, timeout))- HttpUrlFetcher 做网络请求 }
  2. 从上面的SourceGenerator .startNext()继续-->startNextLoad()-->HttpUrlFetcher.loadData()
public void loadData() {
  //loadDataWithRedirects方法就是网络请求
    InputStream result = loadDataWithRedirects(
      glideUrl.toURL(), 0, null, glideUrl.getHeaders());
    callback.onDataReady(result);
}
  1. result会一层一层向上回调,一层一层包装,onDataReady(result)-->SourceGenerator .onDataReadyInternal()-->DecodeJob.onDataFetcherReady()–>decodeFromRetrievedData()–>decodeFromData()-->decodeFromFetcher()–>runLoadPath()–>path.load()–>loadWithExceptionList()–>path.decode()–>decodeResource()–>decodeResourceWithList()–>decoder.decode()–>StreamBitmapDecoder.decode() 返回值Resource<Bitmap> 终于把stream转变为了Bitmap
// 这里的Resource<Transcode>会被转成Resource<Bitmap>
  public Resource<Transcode> decode(
      DataRewinder<DataType> rewinder,
      int width,
      int height,
      @NonNull Options options,
      DecodeCallback<ResourceType> callback)
      throws GlideException {
    // 把stream转变为了Bitmap
    Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);
    // 回调
    Resource<ResourceType> transformed = callback.onResourceDecoded(decoded);
    return transcoder.transcode(transformed, options);
  }
  1. 然后回调会一层一层向上,并且会对bitmap进行各种操作,具体的链路不写了(妈的已经崩溃了…)。最终会会掉到ImageViewTarget去显示图片。
总结

Glide的源码看着很痛苦,非常多细节没有补充,有可能有不对的地方,希望大家能指正。在后续的学习中也会不断的完善。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值