Glide 4.x工作总体执行流程概述

android图片加载框架最早用的就是ImageLoader,并且对其源码专门弄了个Image Loader专栏分析其源码,后来项目中也用过Fresco以及Glide等,但是一直没有静下心来深入其Glide等源码内部了解他们的原理,所以本系列就基于Glide 4.2.0的版本对其进行剖析(4.x的版本与3.x的版本还是有些差异性的),因为Glide源码着实复杂,所以本篇作为Glide源码分析的第一篇文章不会涉及太深太杂的内容,需要徐徐图之。

Glide的使用方法也很简单,一句代码的事儿:

 Glide.with(this).load(imageUrl).into(imageView);

如果将此代码按步骤进行划分的话,就可拆分成如下几行代码:

//构建RequestManager对象
 RequestManager requestManager = Glide.with(this);
 //构建
 RequestBuilder<Drawable> requestBuilder = requestManager.load("http://");

 Target target =requestBuilder.into(new ImageView(this));

上面三行代码也很简单:
1、调用Glide.with(this)创建一个RequestManager对象。
2、requestManager对象load一个图片URL返回RequestBuilder对象(其范型类型为Drawable)。
3、requestBuilder调用into方法使注入的ImageView显示对应url的图片

简简单单的代码背后其实隐藏大部分的逻辑,比如:

1、Glide内部是通过什么来发起http请求的?
2、Glide缓存是怎么工作的呢?
3、into方法执行后返回一个Target对象,为什么into都可以把任务完成了,还返回一个target对象干嘛的?Target是什么鬼?
4、RequsetBuilder顾名思义就是构建一个Request,那么Request在上面的代码中怎么没有体现?

仅仅从上面代码上来看,一脸蒙逼。。。就像看某类动作片都是马赛克一样,看不清细节,令人不痛快(奸笑)。下面就逐步开始剔除万恶的马赛克,揭露glide的内部细节。阅读Gide的源码着实比阅读ImageLoader的源码困难,在阅读的过程中也着实学了不少东西,下面正式开始吧。

RequestManager的创建过程

构建RequestManager的过程,是Glide通过调用with方法返回的,所以看看with方法都做了些什么(以activity为参数的with方法为例):

  public static RequestManager with(Activity activity) {
    return getRetriever(activity).get(activity);
  }

witch方法先内部调用了getRetriever方法:

 static RequestManagerRetriever getRetriever(Context context) {

   return Glide.get(context).getRequestManagerRetriever();
  }

getRetriever 方法返回一个RequestManagerRetriever对象,也就是说RequestManager对象是由RequestManagerRetriever来构建的,那么该对象是什么时候初始化的呢?先看看Glide的get方法:

 public static Glide get(Context context) {
    if (glide == null) {
      synchronized (Glide.class) {
        if (glide == null) {
          checkAndInitializeGlide(context);
        }
      }
    }

    return glide;
  }

如上所示Glide也是一个单利模式,checkAndInitializeGlide方法内部调用了initializeGlide方法来初始化Glide,剔除与本文无关的代码逻辑initializeGlide可以如下所示:

 private static void initializeGlide(Context context) {

   //省略部分代码
   GlideBuilder builder = new GlideBuilder()
        .setRequestManagerFactory(factory);
    //省略部分代码
    //通过构建着模式创建Glide对象
    Glide glide = builder.build(applicationContext);
     //省略部分代码
    Glide.glide = glide;
  }

上面省略了大量的代码后发现初始化Glide也是一个创建者模式,进入builder的build方法看看是怎么初始化的,现在我们在探讨RequestManagerRetriever的构建过程,所以还是省略了无关的代码来看:

 public Glide build(Context context) {
    //省略部分代码

    //初始化Glide持有的RequestManagerRetriever对象
    RequestManagerRetriever requestManagerRetriever = new RequestManagerRetriever(requestManagerFactory);

    return new Glide(
         。。。。,
        requestManagerRetriever,
        。。。。);
  }

可以看出Glide的RequestManagerRetriever初始化也很简单,另外需要注意的是该对象需要一个requestManagerFactory对象,如果requestManagerFactory对象客户端没有设置的话则使用glide默认的对象:

//熟悉的handler
private final Handler handler;
private final RequestManagerFactory factory;

 public RequestManagerRetriever(@Nullable RequestManagerFactory factory) {
    this.factory = factory != null ? factory : DEFAULT_FACTORY;
    handler = new Handler(Looper.getMainLooper(), this );
  }

默认的RequestManagerFactory为DEFAULT_FACTORY,

 //构建RequestManager的工厂类
  private static final RequestManagerFactory DEFAULT_FACTORY = new RequestManagerFactory() {

    public RequestManager build(Glide glide, Lifecycle lifecycle,
        RequestManagerTreeNode requestManagerTreeNode) {
      return new RequestManager(glide, lifecycle, requestManagerTreeNode);
    }
  };

到此为止RequestManagerRetriever对象已经构建完毕,上文提到是通过RequestManagerRetriever对象的get方法来获取RequestManger对象的,所以让我们看看其get方法都做了些神马:

  public RequestManager get(Activity activity) {
    if (Util.isOnBackgroundThread()) {
      return get(activity.getApplicationContext());
    } else {

      android.app.FragmentManager fm = activity.getFragmentManager();
      //调用fragmentGet方法返回RequestManager对象
      return fragmentGet(activity, fm, null );
    }
  }

直接进入fragmentGet方法来看RequestManger的创建过程:

private RequestManager fragmentGet(Context context, android.app.FragmentManager fm,
      android.app.Fragment parentHint) {

    RequestManagerFragment current = getRequestManagerFragment(fm, parentHint);

RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
      //初始化RequestManager
      Glide glide = Glide.get(context);
      requestManager =
          factory.build(glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode());
      current.setRequestManager(requestManager);
    }
    return requestManager;
  }

也就是说第一次初始化的时候调用上所说的工厂类DEFAULT_FACTORY来创建RequestManager.再次使用的话就是从RequestManagerFragment对象中获取了。

分析道这儿RequestManager对象的构建步骤分析完毕,总结下来也就是:
1、Glide初始化的时候先创建一个RequestManagerRetriever对象,并且该对象持有一个构建RequestManager对象的工厂接口RequestManagerFactory。该接口客户端可以使用自己的实现来构建RequestManager对象,也可以使用Glide 默认的工厂接口实现类DEFAULT_FACTORY。
2、通过RequestManagerRetriever的get方法来初始化RequestManager,说白了就是调用factory的build方法来完成RequestManager的构建。

另外需要注意的是,上面只是极尽简化的说明来RequestManager的构建过程,对于其内部大量的细节都暂时忽略,这样可以使得本文调理清晰点,至于更复杂的内部细节,会另开博文说明。

RequestBuilder 的构建

RequestManager对象构建完毕,那么通过requestManager.load(“http://”);方法返回的RequesBuilder又是如何构建的呢?

//requestManager的load方法
public RequestBuilder<Drawable> load(@Nullable Object model) {
    return asDrawable().load(model);
  }

 //asDrawable
 public RequestBuilder<Drawable> asDrawable() {
    return as(Drawable.class);
  }

public <ResourceType> RequestBuilder<ResourceType> as(Class<ResourceType> resourceClass) {
    return new RequestBuilder<>(glide, this, resourceClass);
  }

如上所示load最终先调用asDrawable方法,然后调用as 方法将RequestBuidler的范型设置为Drawable并new一个RequestBuilder对象:


  protected RequestBuilder(Glide glide, RequestManager requestManager,
      Class<TranscodeType> transcodeClass) {
    this.glide = glide;
    this.requestManager = requestManager;
    //注意该context是GlideContext对象
    this.context = glide.getGlideContext();
    //在本文中为Drawable.class
    this.transcodeClass = transcodeClass;
    //获取默认的请求参数
    this.defaultRequestOptions = requestManager.getDefaultRequestOptions();
    //获取默认的TransitionOptions对象
    this.transitionOptions = requestManager.getDefaultTransitionOptions(transcodeClass);
    this.requestOptions = defaultRequestOptions;
  }

asDrawable方法调用完毕后就调用load(model)方法:

  public RequestBuilder<TranscodeType> load(@Nullable Object model) {
    return loadGeneric(model);
  }
  //loadGeneric
 private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
    this.model = model;//image url
    isModelSet = true;
    return this;
  }

如上所示load 方法进而调用了loadGeneric方法,该方法就是设置了model属性(再此可以看为图片的url)和isModelSet变量

到此为止RequestBuilder对象也就构建完毕了,那么RequestBuilders是干什么呢?顾名思义,该对象也是使用了构建者模式,目的就是构建Request对象!!!requestBuilder对象创建完成后我们就可以调用into方法来显示图片了:

Target简单说明

 public Target<TranscodeType> into(ImageView view) {
    //省略对图片设置参数的处理代码
    return into(context.buildImageViewTarget(view, transcodeClass), requestOptions);
  }

into方法最终调用了另外一个into重载方法,在调用重载方法之前先调用GlideContext对象的buildImageViewTarget方法,在Glide通过GlideBuilder调用Glide构造器创建的时候,在Glide构造器内部初始化来GlideContext对象,代码如下:

 //创建ImageViewTargetFactory对象
 ImageViewTargetFactory imageViewTargetFactory = new ImageViewTargetFactory();

   //初始化GlideContext对象
    glideContext =
        new GlideContext(
            context, registry, imageViewTargetFactory, defaultRequestOptions,
            defaultTransitionOptions, engine, logLevel);

现在我们来看看GlideContext的buildImageViewTarget都做了些神马

 public <X> Target<X> buildImageViewTarget(ImageView imageView, Class<X> transcodeClass) {
    return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
  }

代码很简单就是调用了ImageViewTargetFactory来创建一个Target:

public class ImageViewTargetFactory {

  @SuppressWarnings("unchecked")
  public <Z> Target<Z> buildTarget(ImageView view, Class<Z> clazz) {
    if (Bitmap.class.equals(clazz)) {
      return (Target<Z>) new BitmapImageViewTarget(view);
    } else if (Drawable.class.isAssignableFrom(clazz)) {
      return (Target<Z>) new DrawableImageViewTarget(view);
    } else {
       //抛异常
    }
  }
}

因为上文我们传的是Drawable,所以此时的工厂类返回的是一个DrawableImageViewTarget对象,该对象持有一个目标ImageView的引用。buildImageViewTarget调用完毕后紧接着将生成的target对象交给了into重载方法,如下:

  public <Y extends Target<TranscodeType>> Y into(@NonNull Y target) {
    return into(target, getMutableOptions());
  }

该into重载方法继而有调用了另外一个重载方法:

  //该方法最终也是返回一个Target
  private <Y extends Target<TranscodeType>> Y into(@NonNull Y target, RequestOptions options) {
   //省略部分代码
    options = options.autoClone();
    //构建reqeust对象
    Request request = buildRequest(target, options);

    //省略部分代码:此部分以后说明

    requestManager.clear(target);
    target.setRequest(request);
    //注意此句,文章后面会有着重说明
    requestManager.track(target, request);

    return target;
  }

至此into方法调用完毕,该方法执行的结果是返回一个Target接口的实现类,Glide本身提供类各种Target实现类,看下图先做个简单的直观印象,在本文中返回的是一个DrawableImageViewTarget对象:
这里写图片描述

Request对象简单说明

如上文所示我们先构建了RequestBuilder对象,根据其名称我们可以猜出RequestBuilder对象的作用就是创建Ruquest对象,在最后一个into方法调用的时候调用了如下代码来构建Request对象:

 Request request = buildRequest(target, options);

在Glide中Request是一个接口,Glide对此接口有两个实现类:ThumbnailRequestCoordinator和SingleRequest。 现在让我们先看看buildRequest方法都做了什么:

private Request buildRequest(Target<TranscodeType> target, RequestOptions requestOptions) {
    return buildRequestRecursive(target, null, transitionOptions, requestOptions.getPriority(),
        requestOptions.getOverrideWidth(), requestOptions.getOverrideHeight(), requestOptions);
  }

直接调用了buildRequestRecursive方法,所以进入其内部观看源码 :

private Request buildRequestRecursive(。。。) {
    if (thumbnailBuilder != null) {
      //省略大量代码
      ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
     //省略大量代码
      return coordinator;
    } else if (thumbSizeMultiplier != null) {

      ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
      //省略部分代码
      return coordinator;
    } else {
      // Base case: no thumbnail.
      //本文分析这个分支
      return obtainRequest(target, requestOptions, parentCoordinator, transitionOptions, priority,
          overrideWidth, overrideHeight);
    }
  }

因为在文章开头中我们只设置了URL,最终会走到obtainRequest方法中,该方法就是简单的return一个SingleRequest对象

 return SingleRequest.obtain(
        context,
        model,//url
         //省略部分参数,
        context.getEngine(),
        。。);

到此为止请求Request对象构建完毕,因为篇幅较长,此时来梳理下Glide的工作:
1、通过GlideBuilder来构建Glide对象
2、构建Glide对象的时候创建RequestManagerRetriever对象
3、通过RequestManangerRetriever对象持有的工厂类requestManagerFactory来构建RequestManager对象。
4、RequestManager调用load方法构建一个RequestBuilder对象
5、RequestBuilder对象在调用into方法的时候会调用buildRequest对象来build一个Request对象,同时会into方法会通过ImageViewTargetFactory工厂类来返回一个具体的Target对象。

  • 发起网络请求,加载网络图片

那么Request对象创建完毕了,何时发起请求呢?还记得前文构建Request对象之后有一句代码么?在上面我特别加了注释 “注意此句,文章后面会有着重说明”:

//注意此句,文章后面会有着重说明
    requestManager.track(target, request);

Request创建号之后会将生成的target(此处以DrawableIamgeViewTarget 为例)和request(此处分析SingleRequest)交给RequestManager对象来处理,顾名思义RequestManager的作用就是Manage Request!所以进入track内部:

  void track(Target<?> target, Request request) {
    targetTracker.track(target);
    //执行reqeust
    requestTracker.runRequest(request);
  }

track方法调用来runRequest方法来执行请求:

 public void runRequest(Request request) {
    requests.add(request);
    if (!isPaused) {
       //发起请求
      request.begin();
    } else {
      pendingRequests.add(request);
    }
  }

runRequest方法也就是调用来request接口的begin 方法来发起请求或者说是执行异步加载:

/**
   * Starts an asynchronous load.
   */
  void begin();

以SingleReqeust为例,看看其begin方法都做了些什么:

public void begin() {

   //省略部分代码

    //如果资源已经存在
    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);
    }

    if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)
        && canNotifyStatusChanged()) {
       //设置图片的placeHolder图片
      target.onLoadStarted(getPlaceholderDrawable());
    }

  }

总体来说上面的代码也很简单:
1、如果资源已经存在则调用onResourceReady方法
2、否则调用onSizeReady同时会设置placeholder
先分析其onResourceReady方法,该方法经过最终会调用 target.onResourceReady(result, animation);如果以DrawableImageViewTarget为例的话最终target.onResourceReady会调用DrawableImageViewTarget的setResource

 protected void setResource(@Nullable Drawable resource) {  //该view就是通过into方法传过来的ImageView
    view.setImageDrawable(resource);
  }

setResource也很简单,就是将生成的resource 这个Drawable对象交给ImageView的setImageDrawable方法,这样就可以完成图片的展示了。
至于onSizeReady鉴于其内部逻辑很复杂,就敬请阅读《Glide获取网络图片流程

到此为止Glide内部的工作流程基本分析完毕,结合上文简单来说就是通过RequestBuilder创建一个Requset对象之后,调用request对像的begin发起异步加载的请求展示图片的过程。

如有不当之处,欢迎批评之正,共同学习。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

郭梧悠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值