Glide源码解析1:加载请求Request是如何生成的

问题

  1. 我们正常调用Glide时如何开始的异步加载
  2. Glide如何与生命周期相关的

简单使用

Glide.with(this).load(R.drawable.test).into(iv_image)

流程解析

Glide.with()

有多个with方法,这里只以参数是context的来举例

//Glide.java
//通过RequestManagerRetriever实例去获取对应context的RequestManager
public static RequestManager with(@NonNull Context context) {
    return getRetriever(context).get(context);
}

//获取Glide对象中的RequestManagerRetriever实例(RequestManager检索器)
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
    return Glide.get(context).getRequestManagerRetriever();
}

//获取Glide的单例
@NonNull
public static Glide get(@NonNull Context context) {
    //这个双重锁就可以看出来,Glide是单例的
    if (glide == null) {
        //这里的GeneratedAppGlideModule是我们自定义的GlideModle,用于修改如缓存池大小的参数
      GeneratedAppGlideModule annotationGeneratedModule =
          getAnnotationGeneratedGlideModules(context.getApplicationContext());
      synchronized (Glide.class) {
        if (glide == null) {
            //初始化Glide对象,可以自己点进去看一下,里面涉及到了缓存池的初始化等内容,内容比较集中
          checkAndInitializeGlide(context, annotationGeneratedModule);
        }
      }
    }
    
    return glide;
}

由上面代码可得知,这些类的具体作用为

  1. Glide:单例,用于统一管理Glide
  2. RequestManagerRetriever:单例,用于统一管理RequestManager
  3. RequestManager:未知

而上面的内容则表示Glide.with(context)会根据context来获取一个RequestManager。
我们接下来看看RequestManager怎么来的

RequestManagerRetriever.java
  @NonNull
  public RequestManager get(@NonNull Context context) {
    if (context == null) {
      throw new IllegalArgumentException("You cannot start a load on a null Context");
    } else if (Util.isOnMainThread() && !(context instanceof Application)) {
      if (context instanceof FragmentActivity) {
        return get((FragmentActivity) context);
      } else if (context instanceof Activity) {
        return get((Activity) context);
      } else if (context instanceof ContextWrapper
          && ((ContextWrapper) context).getBaseContext().getApplicationContext() != null) {
        //其它context其实还是类似Application的调用
        return get(((ContextWrapper) context).getBaseContext());
      }
    }

    //在子线程,或者context是属于Application的,则调用到这里
    //内部其实是获取一个与Application绑定的RequestManager,变量为applicationManager
    return getApplicationManager(context);
  }
  
//以Activity参数的为例
public RequestManager get(@NonNull Activity activity) {
    if (Util.isOnBackgroundThread()) {
        //若是在子线程,还是直接会返回applicationManager
      return get(activity.getApplicationContext());
    } else {
      assertNotDestroyed(activity);
      android.app.FragmentManager fm = activity.getFragmentManager();
      //注意这里,看方法名貌似会生成一个Fragment
      return fragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
    }
}

//获取一个新的RequestManager实例
private RequestManager fragmentGet(
      @NonNull Context context,
      @NonNull android.app.FragmentManager fm,
      @Nullable android.app.Fragment parentHint,
      boolean isParentVisible) {
    //获取了一个RequestManagerFragment出来
    RequestManagerFragment current = getRequestManagerFragment(fm, parentHint, isParentVisible);
    //从Fragment里取出个RequestManager对象,新创建的是不会有对象的
    RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
      Glide glide = Glide.get(context);
      //通过工厂新建一个RequestManager,注意第二个参数传入了Fragment的lifecycle,是为了让RequestManager可以知道Fragment的生命周期
      requestManager =
          factory.build(
              glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
        //这里把RequestManager存入Fragment中
      current.setRequestManager(requestManager);
    }
    //最终返回RequestManager
    return requestManager;
  }
  
//获取一个绑定上当前界面的Fragment
private RequestManagerFragment getRequestManagerFragment(
  @NonNull final android.app.FragmentManager fm,
  @Nullable android.app.Fragment parentHint,
  boolean isParentVisible) {
    
    //通过tag去找该Fragment是否已经存在
    RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
    if (current == null) {
        //pendingRequestManagerFragments存的是整个进程等待创建的RequestManagerFragment列表
      current = pendingRequestManagerFragments.get(fm);
      if (current == null) {
        current = new RequestManagerFragment();
        current.setParentFragmentHint(parentHint);
        if (isParentVisible) {
        //如果我们的父Activity或父Fragment可见,就直接调用onStart回调
          current.getGlideLifecycle().onStart();
        }
        //先存入等待创建列表
        pendingRequestManagerFragments.put(fm, current);
        //找到了就加到当前FragmentManager上,从而实现生命周期的监听
        fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
        //成功add之后,就从等待创建列表里移除。这里通过handler保证线程安全
        handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
      }
}
return current;
}

由上面一大串代码可知

  1. Glide通过创建一个完全透明的Fragment,并监听它的回调,来实现对生命周期的管理
  2. RequestManager是与FragmentManager一一对应的,即一个Activity/Fragment,都对应一个RequestManager
  3. 所以RequestManager的作用就是管理在同一个生命周期下的所有请求

Glide.with().load()

这里的load方法就是调用的RequestManager的load方法了,以load一个ResourceId为例

//RequestManager.java
public RequestBuilder<Drawable> load(@RawRes @DrawableRes @Nullable Integer resourceId) {
    return asDrawable().load(resourceId);
}

//初始化了一个ResourceType为Drawable.class的RequestBuilder(Request构造器)
public RequestBuilder<Drawable> asDrawable() {
    return as(Drawable.class);
  }
  
public <ResourceType> RequestBuilder<ResourceType> as(
  @NonNull Class<ResourceType> resourceClass) {
    //asDrawable会先new一个RequestBuilder
    return new RequestBuilder<>(glide, this, resourceClass, context);
}
//RequestBuilder.java
public RequestBuilder<TranscodeType> load(@RawRes @DrawableRes @Nullable Integer resourceId) {
    return loadGeneric(resourceId).apply(signatureOf(AndroidResourceSignature.obtain(context)));
}

private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
    //load则只是把load里的输入对象存入了RequestBuilder的model中
    this.model = model;
    isModelSet = true;
    return this;
  }

从上面代码可知

  1. load并没有正式发起请求,只是生成了一个request的构造器
  2. 这个request的构造器包含的信息有输入的对象(这里是资源id),和输出对象的class(这里是Drawable.class)

Glide.with().load().into()

这里是我们实现ImageView展示图片的最后一步,所以请求肯定会在这个方法内发起

//RequestBuilder.java
  public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {

    BaseRequestOptions<?> requestOptions = this;
    if (!requestOptions.isTransformationSet()
        && requestOptions.isTransformationAllowed()
        && view.getScaleType() != null) {
      //若ImageView设置了scaleType,Glide也会把它存入这次request的配置中
      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(
        //这里只是把ImageView和Drawable.class绑定起来生成一个新对象ImageViewTarget便于处理最终结果
        glideContext.buildImageViewTarget(view, transcodeClass),
        /*targetListener=*/ null,
        requestOptions,
        Executors.mainThreadExecutor());
  }
  
private <Y extends Target<TranscodeType>> Y into(
  @NonNull Y target,
  @Nullable RequestListener<TranscodeType> targetListener,
  BaseRequestOptions<?> options,
  Executor callbackExecutor) {
    Preconditions.checkNotNull(target);
    if (!isModelSet) {
      throw new IllegalArgumentException("You must call #load() before calling #into()");
    }

    //这个buildRequest慎入,会把自己看晕,我们要了解的是这个buildRequest只是生成了一个SingleRequest实例而已
    Request request = buildRequest(target, targetListener, options, callbackExecutor);

    //这里的大致意思是如果这个viewTarget已经有一个一样的request请求,且不在运行状态,则直接重新调用它的begin
    Request previous = target.getRequest();
    if (request.isEquivalentTo(previous)
        && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
      if (!Preconditions.checkNotNull(previous).isRunning()) {
        previous.begin();
      }
      return target;
    }

    //把ViewTarget的请求清空
    requestManager.clear(target);
    //把request设置到ImageView的tag上
    target.setRequest(request);
    //见下
    requestManager.track(target, request);
    
    return target;
}

synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
    //targetTracker是Target的统一生命周期管理类,用来调用target的生命周期方法,里面内容比较单一,可以自己看
    targetTracker.track(target);
    //见下面的分析,大意就是开始一次request
    requestTracker.runRequest(request);
  }
  
public void runRequest(@NonNull Request request) {
requests.add(request);
    if (!isPaused) {
      //正式开始request!
      request.begin();
    } else {
      request.clear();
      if (Log.isLoggable(TAG, Log.VERBOSE)) {
        Log.v(TAG, "Paused, delaying request");
      }
      //若当前界面未显示或手动暂停了,则加入pendingRequests列表,防止该Request被系统回收
      pendingRequests.add(request);
    }
}

上面的代码展示了into方法的作用,那么大段

  1. 通过RequestBuilder对象生成一个Request,分别存入RequestTracker和view中
  2. 执行这个Request

最后总结一下本文出现的各个类的作用:

  1. Glide:单例,用于统一管理Glide
  2. RequestManagerRetriever:单例,用于获取RequestManager
  3. RequestManager:请求管理器,一个界面对应一个RequestManager
  4. RequestBuilder:Request的构造者
  5. Request:我们的一次加载请求

问题解答

  1. 我们正常调用Glide时如何开始的异步加载?Glide会根据传入的context拿到对应的RequestManager,并根据load传入的资源生成一个Request请求,最后调用Request.begin正式开始这次加载请求(注意我们这次源码分析一直都是在主线程进行的,其实还并没有分析到异步加载的地方)
  2. Glide如何绑定生命周期的?通过在当前页面add一个透明的Fragment实现的生命周期监听,Fragment在跳转对应生命周期时会回调给ViewTarget
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值