Glide源码分析(一)

先写一个简单的例子:

  Glide.with(context).load(url).into(imageView);

看源码我们要记住一个原则,就是站在宏观的角度先去理解他。再慢慢延伸到细节。glide的源码比较多。我们先沿着主线去一步步分析它。glide使用了外观模式,一般第三方的sdk通常都会这么做,节省用户学习使用的成本。我们来看看glide.with。

1.Glide#with

这里就是返回一个requestManager。有6中重载的方法,我们这里就以通常的activity来处理。

2.Glide#getRetriever

这里就是做了一个非空判断,然后我们先看Glide.get。

3.Glide#get

这里就是生成一个单例的glide对象。当然里面通过GlideBuilder构建glide的配置。比如缓存策略等。我们回到2,接着看一下getRequestManagerRetriever。

4.Glide#getRequestManagerRetriever

这里就是拿到glide初始化的时候生成的requestManagerRetriever。我们来看一下glide生成时候requestManagerRetriever的生成过程。

5.GlideBuilder#build

Glide build(@NonNull Context context) {
   ...
    RequestManagerRetriever requestManagerRetriever =
        new RequestManagerRetriever(requestManagerFactory);

    return new Glide(
        context,
        engine,
        memoryCache,
        bitmapPool,
        arrayPool,
        requestManagerRetriever,
        connectivityMonitorFactory,
        logLevel,
        defaultRequestOptions.lock(),
        defaultTransitionOptions);
  }
这里我们知道requestManagerFactory在本例中为空。然后看一下RequestManagerRetriever构造。

6.RequestManagerRetriever#RequestManagerRetriever

 

 public RequestManagerRetriever(@Nullable RequestManagerFactory factory) {
    this.factory = factory != null ? factory : DEFAULT_FACTORY;
    handler = new Handler(Looper.getMainLooper(), this /* Callback */);
  }
 
初始化了一个主线程的handler,这里factory为null 继续看DEFAULT_FACTORY。

7.RequestManagerRetriever#DEFAULT_FACTORY 

 

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



这里生成RequestManagerRetriever的时候实现了RequestManagerFactory接口来提供requestManager实例。好了,这时候我们可以回到第一步看一下get方法。

8.RequestManagerRetriever#get

这里先是判断activity在不在前台,我们这里按前台处理,还是一个原则,宏观处理沿着一条主线走下去。

接着判断activity没有销毁,得到FragmentManager,最后看一下fragmentGet方法。

9.RequestManagerRetriever#fragmentGet

   private RequestManager fragmentGet(@NonNull Context context,
      @NonNull android.app.FragmentManager fm,
      @Nullable android.app.Fragment parentHint,
      boolean isParentVisible) {
    RequestManagerFragment current = getRequestManagerFragment(fm, parentHint, isParentVisible);
    RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
      // TODO(b/27524013): Factor out this Glide.get() call.
      Glide glide = Glide.get(context);
      requestManager =
          factory.build(
              glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
      current.setRequestManager(requestManager);
    }
    return requestManager;
  }

接着我们来看一下getRequestManagerFragment方法。

10.RequestManagerRetriever#getRequestManagerFragment

  private RequestManagerFragment getRequestManagerFragment(
      @NonNull final android.app.FragmentManager fm,
      @Nullable android.app.Fragment parentHint,
      boolean isParentVisible) {
    RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
    if (current == null) {
      current = pendingRequestManagerFragments.get(fm);
      if (current == null) {
        current = new RequestManagerFragment();
        current.setParentFragmentHint(parentHint);
        if (isParentVisible) {
          current.getGlideLifecycle().onStart();
        }
        pendingRequestManagerFragments.put(fm, current);
        fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
        handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
      }
    }
    return current;
  }

这里先从fragmentManager中获取是否有RequestManagerFragment,这里第一次是没有的,然后判断pendingRequestManagerFragments有没有。为什么还需要pendingRequestManagerFragments辅助判断呢,因为fragmentManager是以消息机制的方法提交的,这里不可避免的会延迟。使用pendingRequestManagerFragments避免创建两次。这里glide使用了一个很巧妙的方式来绑定activity的生命周期,就是通过创建一个activity的fragment来间接监听activity的生命周期。通过RequestManagerFragment中ActivityFragmentLifecycle类来通知各个实现LifecycleListener接口的类。这里得到RequestManagerFragment,我们回到第9步。第一次是没有RequestManager的。我们通过glide初始化的factory。最终得到生成的requestManager对象。接着,我们load方法。

10.RequestManager#load

这里返回的是RequestBuilder。显然是request的各种配置类。我们接着来看一下asDrawable方法。

11.RequestManager#asDrawable

  @NonNull
  @CheckResult
  public RequestBuilder<Drawable> asDrawable() {
    return as(Drawable.class);
  }
  @NonNull
  @CheckResult
  public <ResourceType> RequestBuilder<ResourceType> as(
      @NonNull Class<ResourceType> resourceClass) {
    return new RequestBuilder<>(glide, this, resourceClass, context);
  }
这里扩展一个小知识,就是使用一个未定义的泛型时,应该如上这样写。这里拿到生成的RequestBuilder。这里面会涉及图片加载参数的设置。我们再回到第10步。看一下load方法

12.RequestBuilder#load

这里会把url赋值给model,并且把ismodelset置为true(说明model已经被赋值)。这样load方法就分析完了。我们来看一下into。

13.RequestBuilder#into

  public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
    Util.assertMainThread();
    Preconditions.checkNotNull(view);

    RequestOptions requestOptions = this.requestOptions;
    if (!requestOptions.isTransformationSet()
        && requestOptions.isTransformationAllowed()
        && view.getScaleType() != null) {
      // Clone in this method so that if we use this RequestBuilder to load into a View and then
      // into a different target, we don't retain the transformation applied based on the previous
      // View's scale type.
      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(
        glideContext.buildImageViewTarget(view, transcodeClass),
        /*targetListener=*/ null,
        requestOptions);
  }

这里先判断了是否在主线程,非空判断。获取设置的RequestOptions,因为这里我们没有设置所以为第5步GlideBuilder生成过程中默认的RequestOptions。所以我们可以略过这段配置直接看下面的into,先来看into的第一个参数buildImageViewTarget。

14.GlideContext#buildImageViewTarget

 

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

因为transcodeClass就是我们第11步传的drawable。很明显我们会返回一个DrawableimageViewTarget类。我们接着返回13步看一下into方法。 

15.RequestBuilder#into

  private <Y extends Target<TranscodeType>> Y into(
      @NonNull Y target,
      @Nullable RequestListener<TranscodeType> targetListener,
      @NonNull RequestOptions options) {
    Util.assertMainThread();
    Preconditions.checkNotNull(target);
    if (!isModelSet) {
      throw new IllegalArgumentException("You must call #load() before calling #into()");
    }

    options = options.autoClone();
    Request request = buildRequest(target, targetListener, options);

    Request previous = target.getRequest();
    if (request.isEquivalentTo(previous)
        && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
      request.recycle();
      // If the request is completed, beginning again will ensure the result is re-delivered,
      // triggering RequestListeners and Targets. If the request is failed, beginning again will
      // restart the request, giving it another chance to complete. If the request is already
      // running, we can let it continue running without interruption.
      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;
    }

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

    return target;
  }

先是同样的判断主线程,非空。isModelSet是否设置,得到RequestOptions,接着我们看一下buildRequest方法。

16.RequestBuilder#buildRequest

 private Request buildRequestRecursive(
      Target<TranscodeType> target,
      @Nullable RequestListener<TranscodeType> targetListener,
      @Nullable RequestCoordinator parentCoordinator,
      TransitionOptions<?, ? super TranscodeType> transitionOptions,
      Priority priority,
      int overrideWidth,
      int overrideHeight,
      RequestOptions requestOptions) {

    // Build the ErrorRequestCoordinator first if necessary so we can update parentCoordinator.
    ErrorRequestCoordinator errorRequestCoordinator = null;
    if (errorBuilder != null) {
      errorRequestCoordinator = new ErrorRequestCoordinator(parentCoordinator);
      parentCoordinator = errorRequestCoordinator;
    }

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

    if (errorRequestCoordinator == null) {
      return mainRequest;
    }

    int errorOverrideWidth = errorBuilder.requestOptions.getOverrideWidth();
    int errorOverrideHeight = errorBuilder.requestOptions.getOverrideHeight();
    if (Util.isValidDimensions(overrideWidth, overrideHeight)
        && !errorBuilder.requestOptions.isValidOverride()) {
      errorOverrideWidth = requestOptions.getOverrideWidth();
      errorOverrideHeight = requestOptions.getOverrideHeight();
    }

    Request errorRequest = errorBuilder.buildRequestRecursive(
        target,
        targetListener,
        errorRequestCoordinator,
        errorBuilder.transitionOptions,
        errorBuilder.requestOptions.getPriority(),
        errorOverrideWidth,
        errorOverrideHeight,
        errorBuilder.requestOptions);
    errorRequestCoordinator.setRequests(mainRequest, errorRequest);
    return errorRequestCoordinator;
  }
这里因为没有设置errorBuilder,我直接往下看。看一下buildThumbnailRequestRecursive方法。

17.RequestBuilder#buildThumbnailRequestRecursive

private Request buildThumbnailRequestRecursive(
      Target<TranscodeType> target,
      RequestListener<TranscodeType> targetListener,
      @Nullable RequestCoordinator parentCoordinator,
      TransitionOptions<?, ? super TranscodeType> transitionOptions,
      Priority priority,
      int overrideWidth,
      int overrideHeight,
      RequestOptions requestOptions) {
    if (thumbnailBuilder != null) {
    ...
    } else if (thumbSizeMultiplier != null) {
    ...
    } else {
      // Base case: no thumbnail.
      return obtainRequest(
          target,
          targetListener,
          requestOptions,
          parentCoordinator,
          transitionOptions,
          priority,
          overrideWidth,
          overrideHeight);
    }
  }
好吧又是一个很长的方法...继续看。因为我们没有设置thumbnailBuilder和thumbSizeMultiplier。我们直接看最后面obtainRequest方法。

18.RequestBuilder#obtainRequest

  private Request obtainRequest(
      Target<TranscodeType> target,
      RequestListener<TranscodeType> targetListener,
      RequestOptions requestOptions,
      RequestCoordinator requestCoordinator,
      TransitionOptions<?, ? super TranscodeType> transitionOptions,
      Priority priority,
      int overrideWidth,
      int overrideHeight) {
    return SingleRequest.obtain(
        context,
        glideContext,
        model,
        transcodeClass,
        requestOptions,
        overrideWidth,
        overrideHeight,
        priority,
        target,
        targetListener,
        requestListeners,
        requestCoordinator,
        glideContext.getEngine(),
        transitionOptions.getTransitionFactory());
  }
然后是obtain方法。

19.SingleRequest#obtain

  public static <R> SingleRequest<R> obtain(
      Context context,
      GlideContext glideContext,
      Object model,
      Class<R> transcodeClass,
      RequestOptions requestOptions,
      int overrideWidth,
      int overrideHeight,
      Priority priority,
      Target<R> target,
      RequestListener<R> targetListener,
      @Nullable List<RequestListener<R>> requestListeners,
      RequestCoordinator requestCoordinator,
      Engine engine,
      TransitionFactory<? super R> animationFactory) {
    @SuppressWarnings("unchecked") SingleRequest<R> request =
        (SingleRequest<R>) POOL.acquire();
    if (request == null) {
      request = new SingleRequest<>();
    }
    request.init(
        context,
        glideContext,
        model,
        transcodeClass,
        requestOptions,
        overrideWidth,
        overrideHeight,
        priority,
        target,
        targetListener,
        requestListeners,
        requestCoordinator,
        engine,
        animationFactory);
    return request;
  }
这里用了一种享元的一种设计模式。可以节省内存开销。有就得到request。当然第一次是没有的。最后init方法只是一下参数设置,我们就不看了。我们回到第15步继续看into方法。

这里判断了是否可以复用。很明显没有上次请求过。接着看一下clear方法。

20.RequestManager#clear

当是主线程的是或者非主线程时处理逻辑是一样的。这里就是看是否这个target有绑定的request,有的话解绑一下。把这个target绑定到这个新的request上去。回到第15步,track方法。

21.RequestManager#track

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

其实就是处理target和request在生命周期变化时而变化。比如暂停,重新开始等等。最后分析一下runRequest方法。

22.RequestTracker#runRequest

如果是暂停的状态,request就会走clear方法,并且把这个request加入到准备加载的pendingrequests集合中(因为requests是weakhashmap 容易被回收,这里放入到pendingrequests里也是防止被回收)。如果是活跃的状态,则会执行begin方法。接下来,我们看看request.begin方法。

23.SingleRequest#begin

这里的model就是我们设置的url,当是null的时候直接调用onLoadFailed方法返回失败。不可能开启一个已经标记为RUNNING的request。如果标记为COMPLETE。直接返回onresourceReady。做下载后的处理。这里我们是第一次使用,所以我们会走下面的过程,这里赋值WAITIND_FOR_SIZE.当没有overrideWidth和overrideHeight无效时,我们来等待view的绘制。这里我们假设绘制好了,我们来看一下onSizeReady。

24.SingleRequest#onSizeReady

这里就是先判断一下是否在等待view的绘制。如果没有直接结束。绘制完成的话赋值RUNNING。然后loadStatus = engine.load。初始化一些缓存策略,图片显示策略等待。这里engine比较复杂,我们先看他的结果是怎么处理的。当engine调用load的时候会把当前的SingleRequest的回调绑定到Engine中。这样我们来看一下ResourceCallback。

所以,当engine处理完就把结果交给SingleRequest来处理,最终交给target。我们最后回到23步。符合条件的时候加载target的占位图。

到这里就结束了整个流畅,下一章我们来分析一些engine的过程。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值