Glide源码学习

news2024/11/25 1:03:14

前言

开始

基本使用非常简单,链式调用把context对象传入,设置要加载的URL,设置要填充的ImageView控件,方法很简洁,每次都是传入的最核心的参数,底层加载的缓存逻辑,加载的引擎,加载的对象的适配,URL的适配…都为我们做了封装。使用者无需关心这些细节就可以实现图片的加载。这才是优秀的库该有的样子足够简洁,但是足够强大。把复杂留给自己,把简单留给用户。

Glide.with(fragment)
    .load(myUrl)
    .into(imageView);

With方法

前面看了Glide的基本使用,Glide是外观类,我们先看前面例子中的with方法

with相关的重载方法有四个,最终都是返回一个RequestManager,后面调用load方法用的就是返回的RequestManager。

@NonNull
public static RequestManager with(@NonNull Context context) {
    return getRetriever(context).get(context);
}

@NonNull
public static RequestManager with(@NonNull FragmentActivity activity) {
    return getRetriever(activity).get(activity);
}

@NonNull
public static RequestManager with(@NonNull Fragment fragment) {
    return getRetriever(fragment.getContext()).get(fragment);
}

@NonNull
public static RequestManager with(@NonNull View view) {
    return getRetriever(view.getContext()).get(view);
}
 

都是先调用getRetriever(),getRetriever()方法是Glide的静态方法,会返回一个RequestManagerRetriever。这个方法中会引出Glide的构造,最终通过调用Glide实例的getRequestManagerRetriever方法返回RequestManagerRetriever。

@NonNull
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
    // Context could be null for other reasons (ie the user passes in null), but in practice it will
    // only occur due to errors with the Fragment lifecycle.
    Preconditions.checkNotNull(context, DESTROYED_ACTIVITY_WARNING);
    return Glide.get(context).getRequestManagerRetriever();
}

//双重校验锁单例模式获取Glide,glide实例是被volatile修饰
@NonNull
// Double checked locking is safe here.
@SuppressWarnings("GuardedBy")
public static Glide get(@NonNull Context context) {
    if (glide == null) {
      //这里通过反射创建一个GeneratedAppGlideModuleImpl的实例
      GeneratedAppGlideModule annotationGeneratedModule =
          getAnnotationGeneratedGlideModules(context.getApplicationContext());
      synchronized (Glide.class) {
        if (glide == null) {
          //检查是否初始化过Glide
          checkAndInitializeGlide(context, annotationGeneratedModule);
        }
      }
    }

    return glide;
  }

继续看checkAndInitializeGlide方法,检查并初始化Glide

static void checkAndInitializeGlide(
      @NonNull Context context, @Nullable GeneratedAppGlideModule generatedAppGlideModule) {
    // In the thread running initGlide(), one or more classes may call Glide.get(context).
    //初始化中,其他类也可能调用Glide.get
    // Without this check, those calls could trigger infinite recursion.
    //如果没有这个校验,有可能触发无线递归
    
    if (isInitializing) {
      throw new IllegalStateException(
          "Glide has been called recursively, this is probably an internal library error!");
    }
    //标记正在初始化中
    isInitializing = true;
    try {
      initializeGlide(context, generatedAppGlideModule);
    } finally {
      //标记初始化中为false
      isInitializing = false;
    }
  }
  
   @GuardedBy("Glide.class")
  private static void initializeGlide(
      @NonNull Context context, @Nullable GeneratedAppGlideModule generatedAppGlideModule) {
    //新建一个GlideBuilder传入
    initializeGlide(context, new GlideBuilder(), generatedAppGlideModule);
  }
  
  
  private static void initializeGlide(
      @NonNull Context context,
      @NonNull GlideBuilder builder,
      @Nullable GeneratedAppGlideModule annotationGeneratedModule) {
    //获取getApplicationContext,这里我们要知道构造Glide是全局唯一的
    Context applicationContext = context.getApplicationContext();
    List<GlideModule> manifestModules = Collections.emptyList();
    //GlideModule相关处理,先忽略
    ...

    RequestManagerRetriever.RequestManagerFactory factory =
        annotationGeneratedModule != null
            ? annotationGeneratedModule.getRequestManagerFactory()
            : null;
    builder.setRequestManagerFactory(factory);
    for (GlideModule module : manifestModules) {
      module.applyOptions(applicationContext, builder);
    }
    if (annotationGeneratedModule != null) {
      annotationGeneratedModule.applyOptions(applicationContext, builder);
    }
    //构造Glide
    Glide glide = builder.build(applicationContext, manifestModules, annotationGeneratedModule);
    //注册ComponentCallback
    applicationContext.registerComponentCallbacks(glide);
    Glide.glide = glide;
  }

这里注意在initializeGlide方法中用的是applicationContext,不依赖某个Activity,Service,Fragment等。为什么提一下这个,因为后面RequestManager的生成不是这样的,后面做下区分。

@NonNull
  Glide build(
      @NonNull Context context,
      List<GlideModule> manifestModules,
      AppGlideModule annotationGeneratedGlideModule) {
    //设置资源执行器
    if (sourceExecutor == null) {
      sourceExecutor = GlideExecutor.newSourceExecutor();
    }

    //设置磁盘缓存执行器
    if (diskCacheExecutor == null) {
      diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
    }
    
    //设置动画执行器
    if (animationExecutor == null) {
      animationExecutor = GlideExecutor.newAnimationExecutor();
    }

    //设置内存计算器
    if (memorySizeCalculator == null) {
      memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
    }

    //设置连接监控工厂
    if (connectivityMonitorFactory == null) {
      connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();
    }

    //构造Bitmap复用池
    if (bitmapPool == null) {
      int size = memorySizeCalculator.getBitmapPoolSize();
      if (size > 0) {
        bitmapPool = new LruBitmapPool(size);
      } else {
        bitmapPool = new BitmapPoolAdapter();
      }
    }

    if (arrayPool == null) {
      arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes());
    }

    //构造内存缓存
    if (memoryCache == null) {
      memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
    }

    //构造磁盘缓存工厂
    if (diskCacheFactory == null) {
      diskCacheFactory = new InternalCacheDiskCacheFactory(context);
    }

    //创建引擎
    if (engine == null) {
      engine =
          new Engine(
              memoryCache,
              diskCacheFactory,
              diskCacheExecutor,
              sourceExecutor,
              GlideExecutor.newUnlimitedSourceExecutor(),
              animationExecutor,
              isActiveResourceRetentionAllowed);
    }

    if (defaultRequestListeners == null) {
      defaultRequestListeners = Collections.emptyList();
    } else {
      defaultRequestListeners = Collections.unmodifiableList(defaultRequestListeners);
    }

    GlideExperiments experiments = glideExperimentsBuilder.build();
    //新建一个RequestManagerRetriever
    //这里注意后面load方法会用到这个requestManagerRetriever来获取RequestManager
    RequestManagerRetriever requestManagerRetriever =
        new RequestManagerRetriever(requestManagerFactory);

    //构造Glide,传入以上实例作为参数
    return new Glide(
        context,
        engine,
        memoryCache,
        bitmapPool,
        arrayPool,
        requestManagerRetriever,
        connectivityMonitorFactory,
        logLevel,
        defaultRequestOptionsFactory,
        defaultTransitionOptions,
        defaultRequestListeners,
        manifestModules,
        annotationGeneratedGlideModule,
        experiments);
  }

构造方法

Glide(
      @NonNull Context context,
      @NonNull Engine engine,
      @NonNull MemoryCache memoryCache,
      @NonNull BitmapPool bitmapPool,
      @NonNull ArrayPool arrayPool,
      @NonNull RequestManagerRetriever requestManagerRetriever,
      @NonNull ConnectivityMonitorFactory connectivityMonitorFactory,
      int logLevel,
      @NonNull RequestOptionsFactory defaultRequestOptionsFactory,
      @NonNull Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions,
      @NonNull List<RequestListener<Object>> defaultRequestListeners,
      @NonNull List<GlideModule> manifestModules,
      @Nullable AppGlideModule annotationGeneratedModule,
      @NonNull GlideExperiments experiments) {
    this.engine = engine;
    this.bitmapPool = bitmapPool;
    this.arrayPool = arrayPool;
    this.memoryCache = memoryCache;
    this.requestManagerRetriever = requestManagerRetriever;
    this.connectivityMonitorFactory = connectivityMonitorFactory;
    this.defaultRequestOptionsFactory = defaultRequestOptionsFactory;

    // This has a circular relationship with Glide and GlideContext in that it depends on both,
    // but it's created by Glide's constructor. In practice this shouldn't matter because the
    // supplier holding the registry should never be initialized before this constructor finishes.
    GlideSupplier<Registry> registry =
        RegistryFactory.lazilyCreateAndInitializeRegistry(
            this, manifestModules, annotationGeneratedModule);

    ImageViewTargetFactory imageViewTargetFactory = new ImageViewTargetFactory();
    //新建一个GlideContext,并传递大部分构造方法的参数进去
    glideContext =
        new GlideContext(
            context,
            arrayPool,
            registry,
            imageViewTargetFactory,
            defaultRequestOptionsFactory,
            defaultTransitionOptions,
            defaultRequestListeners,
            engine,
            experiments,
            logLevel);
  }

现在getRetriever()方法基本看完,核心就是为我们构造出了Glide单例,然后调用Glide的getRequestManagerRetriever()得到RequestManagerRetriever

@NonNull
public RequestManagerRetriever getRequestManagerRetriever() {
    return requestManagerRetriever;
}

这个requestManagerRetriever在Glide构造方法的时候看到过,构造的时候,新建并传递了requestManagerRetriever参数。现在让我们回退再回到with方法,先通过getRetriever方法得到一个RequestManagerRetriever,然后调用它的get方法。下面去看RequestManagerRetriever的get方法,get方法主要是获取一个RequestManager。基本上跟Glide的with方法一一对应,不一样的是with方法最终都调用到了一个方法,而这个get实现都有些区别。

@NonNull
public RequestManager get(@NonNull Context context) {...}

@NonNull
public RequestManager get(@NonNull FragmentActivity activity) {...}

@NonNull
public RequestManager get(@NonNull Fragment fragment) {...}

@NonNull
public RequestManager get(@NonNull View view) {...}
  

上面这四种,第四种其实是分情况如果找到这个View的Activity,Activity是否是属于FragmentActivity,是FragmentActivity的话是否是属于Fragment等最终是调用前三种的一个,所以主要分为三种类型:

  • 参数为FragmentActivity
  • 参数为Fragment
  • 参数为Context

参数为FragmentActivity

 public RequestManager get(@NonNull FragmentActivity activity) {
    ...
    //是否可见
    boolean isActivityVisible = isActivityVisible(activity);
    //获取Glide单例
    Glide glide = Glide.get(activity.getApplicationContext());
    //调用lifecycleRequestManagerRetriever的getOrCreate
    
    return lifecycleRequestManagerRetriever.getOrCreate(
        activity,
        glide,
        activity.getLifecycle(),
        activity.getSupportFragmentManager(),
        isActivityVisible);
  }

lifecycleRequestManagerRetriever是在RequestManagerRetriever构造方法中新建的,也就意味着Glide单例新建之前已经构造好了lifecycleRequestManagerRetriever实例。

注意第三个参数是getLifecycle,只有ComponentActivity才有这个方法,Activity中是没有这个方法的,这也就是为什么这个参数传入的不是Activity的原因。通过这个Lifecycle可以监控activity的生命周期。也就能及时回收,避免发生内存泄露。

接着看getOrCreate

RequestManager getOrCreate(
      Context context,
      Glide glide,
      final Lifecycle lifecycle,
      FragmentManager childFragmentManager,
      boolean isParentVisible) {
    //断言在主线程,不在的话抛异常
    Util.assertMainThread();
    
    //看名字大概是根据lifecycle为key,获取唯一的RequestManager
    RequestManager result = getOnly(lifecycle);
    if (result == null) {
      //LifecycleLifecycle这名字起的。。其实是它实现了glide自己的Lifecycle
      //同时又实现了Android的LifecycleObserver
      LifecycleLifecycle glideLifecycle = new LifecycleLifecycle(lifecycle);
      //构造一个新的
      result =
          factory.build(
              glide,
              glideLifecycle,
              new SupportRequestManagerTreeNode(childFragmentManager),
              context);
      //存放到lifecycleToRequestManager这个Map中
      lifecycleToRequestManager.put(lifecycle, result);
      glideLifecycle.addListener(
          new LifecycleListener() {
            @Override
            public void onStart() {}

            @Override
            public void onStop() {}

            @Override
            public void onDestroy() {
              lifecycleToRequestManager.remove(lifecycle);
            }
          });
      // This is a bit of hack, we're going to start the RequestManager, but not the
      // corresponding Lifecycle. It's safe to start the RequestManager, but starting the
      // Lifecycle might trigger memory leaks. See b/154405040
      if (isParentVisible) {
        //如果Parent可见,直接执行onStart()方法
        result.onStart();
      }
    }
    //返回RequestManager
    return result;
  }

接着看RequestManager的构建,这里使用的是工厂模式,factory是LifecycleRequestManagerRetriever构造的时候传入的,LifecycleRequestManagerRetriever的构造是在RequestManagerRetriever的构造方法中,也就是Glide构造之前。RequestManagerRetriever的构造方法中传入了factory,为空的话会使用DEFAULT_FACTORY,什么时候不为空呢,就是在initializeGlide方法中annotationGeneratedModule.getRequestManagerFactory()不为空,这里先不深入,我们直接看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) {
            直接new了一个RequestManager
          return new RequestManager(glide, lifecycle, requestManagerTreeNode, context);
        }
      };

最终调用到

RequestManager(
      Glide glide,
      Lifecycle lifecycle,
      RequestManagerTreeNode treeNode,
      RequestTracker requestTracker,
      ConnectivityMonitorFactory factory,
      Context context) {
    this.glide = glide;
    this.lifecycle = lifecycle;
    this.treeNode = treeNode;
    this.requestTracker = requestTracker;
    this.context = context;

    connectivityMonitor =
        factory.build(
            context.getApplicationContext(),
            new RequestManagerConnectivityListener(requestTracker));

    // Order matters, this might be unregistered by teh listeners below, so we need to be sure to
    // register first to prevent both assertions and memory leaks.
    glide.registerRequestManager(this);

    // If we're the application level request manager, we may be created on a background thread.
    // In that case we cannot risk synchronously pausing or resuming requests, so we hack around the
    // issue by delaying adding ourselves as a lifecycle listener by posting to the main thread.
    // This should be entirely safe.
    if (Util.isOnBackgroundThread()) {
      Util.postOnUiThread(addSelfToLifecycle);
    } else {
      lifecycle.addListener(this);
    }
    lifecycle.addListener(connectivityMonitor);

    defaultRequestListeners =
        new CopyOnWriteArrayList<>(glide.getGlideContext().getDefaultRequestListeners());
    setRequestOptions(glide.getGlideContext().getDefaultRequestOptions());
  }

参数为Fragment

基本同参数为FragmentActivity,不同的是lifecycle这里获取的是fragment.getLifecycle(),感兴趣的可以自行查阅源码

参数为Context

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 ContextWrapper
          // Only unwrap a ContextWrapper if the baseContext has a non-null application context.
          // Context#createPackageContext may return a Context without an Application instance,
          // in which case a ContextWrapper may be used to attach one.
          && ((ContextWrapper) context).getBaseContext().getApplicationContext() != null) {
        return get(((ContextWrapper) context).getBaseContext());
      }
    }

    return getApplicationManager(context);
  }

到这里我们了解了RequestManager的生成过程。
总结:With阶段主要为:

  • 获取RequestManagerRetriever,获取过程中若未构建Glide,帮我们构建好Glide单例
  • 有了RequestManagerRetriever,通过RequestManagerRetriever的get方法获取RequestManager,不同的context(Activity,Fragment,ApplicationContext)得到不同的RequestManager

至此,with方法分析完成,为我们完成加载图片前的平台侧准备工作,这里的平台指的是Glide。

load方法解析

前面讲解构造函数知道load(url)是RequestManager的方法,RequestManager是用来管理和启动request的。

A class for managing and starting requests for Glide.

RequestManager是with方法中getRetriever(context).get(context)获取的。getRetriever(context)得到RequestManagerRetriever,然后调用RequestManagerRetriever的get方法获取RequestManager。

现在去看下load方法,这里我们就比较熟悉了,我们知道glide非常贴心的为我们支持了很多类型,Bitmap,url,drawable, 资源id,文件等等。

//RequestManager.java
  public RequestBuilder<Drawable> load(@Nullable Bitmap bitmap) {
    return asDrawable().load(bitmap);
  }
  
  public RequestBuilder<Drawable> load(@Nullable String string) {
    return asDrawable().load(string);
  }
  
  public RequestBuilder<Drawable> load(@Nullable Uri uri) {
    return asDrawable().load(uri);
  }
  
  public RequestBuilder<Drawable> load(@Nullable File file) {
    return asDrawable().load(file);
  }
  
  public RequestBuilder<Drawable> load(@RawRes @DrawableRes @Nullable Integer resourceId) {
    return asDrawable().load(resourceId);
  }
  
  public RequestBuilder<Drawable> load(@Nullable URL url) {
    return asDrawable().load(url);
  }
  
  public RequestBuilder<Drawable> load(@Nullable byte[] model) {
    return asDrawable().load(model);
  }
  
  public RequestBuilder<Drawable> load(@Nullable Object model) {
    return asDrawable().load(model);
  }

他们都调用了一个asDrawable()方法,返回一个RequestBuilder,是一个泛型类,可以处理泛型资源类型的设置选项和开始加载。既然是泛型类,除了这里的Drawable,还用到哪些类型呢?还有Bitmap,GifDrawable,File,这里主要分析核心流程,这里主要看Drawable,也是我们最常用的。下面去看下asDrawable的实现。

  public RequestBuilder<Drawable> asDrawable() {
    return as(Drawable.class);
  }
  
  public <ResourceType> RequestBuilder<ResourceType> as(
      @NonNull Class<ResourceType> resourceClass) {
    //构造RequestBuilder,注意这几个参数,第一个参数是glide对象,第二个是RequestManager自身,
    //第三个是resourceClass,也即是传进来的Drawable.class对象,第四个是上下文
    return new RequestBuilder<>(glide, this, resourceClass, context);
  }

asDrawable()也是返回一个RequestBuilder,前面RequestManager的load方法中都是调用了asDrawable().load方法,也就是RequestBuilder的load方法,说明后面执行load方法的也是新建的这个RequestBuilder执行的。然后再来看下

//RequestBuilder.java
  public RequestBuilder<TranscodeType> load(@Nullable String string) {
    //把参数传过去
    return loadGeneric(string);
  }
  
  @NonNull
  private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
    if (isAutoCloneEnabled()) {
      return clone().loadGeneric(model);
    }
    //这里model是一个Object,也就是可以接受任意类型
    this.model = model;
    isModelSet = true;
    return selfOrThrowIfLocked();
  }
  

其实就是给this.mode赋值,然后设置isModelSet为true,然后返回自身,也就是刚刚新建的RequestBuilder,RequestBuilder是BaseRequestOptions的子类。

//BaseRequestOptions.java
  protected final T selfOrThrowIfLocked() {
    if (isLocked) {
      throw new IllegalStateException("You cannot modify locked T, consider clone()");
    }
    return self();
  }
  
  private T self() {
    return (T) this;
  }

总结:load方法看着比较简单,仅仅是构造了一个RequestBuilder,后面调用的into方法也在RequestBuilder中,所以可以认为这里仅仅是对请求参数的一个准备,适配了所有的类型Bitmap,url,drawable, 资源id,文件等等。

into方法分析

前面主要是拿到了RequestBuilder对象,执行into方法的是在RequestBuilder中

//RequestBuilder.java
@NonNull
  public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
    //检查是否在主线程,否则抛异常
    Util.assertMainThread();
    //检查要显示图片的view是否为空
    Preconditions.checkNotNull(view);

    //赋值BaseRequestOptions,RequestBuilder继承自BaseRequestOptions
    BaseRequestOptions<?> requestOptions = this;
    //判断是否设置Transformation等变换
    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,
        Executors.mainThreadExecutor());
  }

看下传入的几个参数

  • glideContext.buildImageViewTarget(view, transcodeClass) -> 构建一个Target对象
  • null->targetListener传入的为空
  • requestOptions->也就是自身
  • Executor->这里传入的是主线程Executor
    这里我们先看下Target的构造过程,后面会用到
//GlideContext.java
public <X> ViewTarget<ImageView, X> buildImageViewTarget(
      @NonNull ImageView imageView, @NonNull Class<X> transcodeClass) {
    //将ImageView和transcodeClass调用imageViewTargetFactory的buildTarget
    return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
  }
  
  

ImageViewTargetFactory的buildTarget方法是根据transcodeClass类型创建不同的Target,如BitmapImageViewTarget和DrawableImageViewTarget

//ImageViewTargetFactory.java
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)");
    }
  }
//RequestBuilder.java
private <Y extends Target<TranscodeType>> Y into(
      @NonNull Y target,
      @Nullable RequestListener<TranscodeType> targetListener,
      BaseRequestOptions<?> options,
      Executor callbackExecutor) {
    //检查target是否为null
    Preconditions.checkNotNull(target);
    //还记得前面load方法中有设置这个为true
    if (!isModelSet) {
      throw new IllegalArgumentException("You must call #load() before calling #into()");
    }

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

    Request previous = target.getRequest();
    //拿到上一次的request,如果和以前的一样
    if (request.isEquivalentTo(previous)
        && !isSkipMemoryCacheWithCompletePreviousRequest(options, previous)) {
      //如果request已经完成,重新开始以保证结果可以被传递
      //如果request已经失败,重新开始请求,给它第二次成功的机会
      //如果在运行,我们让他继续运行
      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;
    }

    //清空target
    requestManager.clear(target);
    //给target设置为当前的request
    target.setRequest(request);
    //添加追踪,并开始执行
    requestManager.track(target, request);

    return target;
  }

后面分三个方向,这三个方法也是into方法主要做的几件事:

  • 如何构造request
  • 如何请求request
  • 如何把请求结果显示到ImageView上

如何构造request

private Request buildRequest(
      Target<TranscodeType> target,
      @Nullable RequestListener<TranscodeType> targetListener,
      BaseRequestOptions<?> requestOptions,
      Executor callbackExecutor) {
    return buildRequestRecursive(
        /* requestLock= */ new Object(),//请求锁
        target,//目标
        targetListener,//目标监听器,前面看到这里传来的是null
        /* parentCoordinator= */ null,
        transitionOptions,//转换选项
        requestOptions.getPriority(),//请求选项-优先级
        requestOptions.getOverrideWidth(),//请求选项-复写宽度
        requestOptions.getOverrideHeight(),//请求选项-复写高度
        requestOptions,//请求选项
        callbackExecutor //回调执行器
        );
  }
  
  
private Request buildRequestRecursive(...) {

    // Build the ErrorRequestCoordinator first if necessary so we can update parentCoordinator.
    ErrorRequestCoordinator errorRequestCoordinator = null;
    //前面Demo没有设置error,这里为null
    if (errorBuilder != null) {
      errorRequestCoordinator = new ErrorRequestCoordinator(requestLock, parentCoordinator);
      parentCoordinator = errorRequestCoordinator;
    }

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

    if (errorRequestCoordinator == null) {
      return mainRequest;
    }
    ...
    return errorRequestCoordinator;
  }
private Request buildThumbnailRequestRecursive(
      Object requestLock,
      Target<TranscodeType> target,
      RequestListener<TranscodeType> targetListener,
      @Nullable RequestCoordinator parentCoordinator,
      TransitionOptions<?, ? super TranscodeType> transitionOptions,
      Priority priority,
      int overrideWidth,
      int overrideHeight,
      BaseRequestOptions<?> requestOptions,
      Executor callbackExecutor) {
    if (thumbnailBuilder != null) {
      //前面Demo中没有设置thumbnail,不会走到这里先忽略
      ...
    } else if (thumbSizeMultiplier != null) {
      //前面Demo中没有设置thumbnail,不会走到这里先忽略
      ...
    } else {
      // Base case: no thumbnail.
      return obtainRequest(
          requestLock,
          target,
          targetListener,
          requestOptions,
          parentCoordinator,
          transitionOptions,
          priority,
          overrideWidth,
          overrideHeight,
          callbackExecutor);
    }
  }

最后走到obtainRequest,通过SingleRequest.obtain,最终在SingleRequest.java中直接新建了一个SingleRequest

private Request obtainRequest(
      Object requestLock,
      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,
        requestLock,
        model,
        transcodeClass,
        requestOptions,
        overrideWidth,
        overrideHeight,
        priority,
        target,
        targetListener,
        requestListeners,
        requestCoordinator,
        glideContext.getEngine(),
        transitionOptions.getTransitionFactory(),
        callbackExecutor);
  }

如何请求request

通过看Request接口说明,知道begin()是开始一个请求,在前面requestManager.track(target, request);会最终调用到begin()方法。

  //RequestManager.java
  synchronized void track(@NonNull Target<?> target, @NonNull Request request) {
    targetTracker.track(target);
    requestTracker.runRequest(request);
  }
  
  //RequestTracker.java
  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);
    }
  }
public interface Request {
  //启动一个异步请求
  void begin();

  //取消,清空请求
  void clear();

  //暂停请求
  void pause();

  //是否在运行中
  boolean isRunning();

  //请求是否完成
  boolean isComplete();

  //请求是否被clear
  boolean isCleared();

  /**
   * Returns true if a resource is set, even if the request is not yet complete or the primary
   * request has failed.
   */
  boolean isAnyResourceSet();

  //和另一个请求是否相等
  boolean isEquivalentTo(Request other);
}

下面我们去看SingleRequest的begin方法的实现

//SingleRequest.java
public void begin() {
    synchronized (requestLock) {
      assertNotCallingCallbacks();
      stateVerifier.throwIfRecycled();
      startTime = LogTime.getLogTime();
      if (model == null) {
        if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
          width = overrideWidth;
          height = overrideHeight;
        }
        // Only log at more verbose log levels if the user has set a fallback drawable, because
        // fallback Drawables indicate the user expects null models occasionally.
        int logLevel = getFallbackDrawable() == null ? Log.WARN : Log.DEBUG;
        onLoadFailed(new GlideException("Received null model"), logLevel);
        return;
      }

      if (status == Status.RUNNING) {
        throw new IllegalArgumentException("Cannot restart a running request");
      }

      // If we're restarted after we're complete (usually via something like a notifyDataSetChanged
      // that starts an identical request into the same Target or View), we can simply use the
      // resource and size we retrieved the last time around and skip obtaining a new size, starting
      // a new load etc. This does mean that users who want to restart a load because they expect
      // that the view size has changed will need to explicitly clear the View or Target before
      // starting the new load.
      if (status == Status.COMPLETE) {
        onResourceReady(
            resource, DataSource.MEMORY_CACHE, /* isLoadedFromAlternateCacheKey= */ false);
        return;
      }

      // Restarts for requests that are neither complete nor running can be treated as new requests
      // and can run again from the beginning.

      experimentalNotifyRequestStarted(model);

      cookie = GlideTrace.beginSectionAsync(TAG);
      status = Status.WAITING_FOR_SIZE;
      if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
        //如果overrideWidth,overrideHeight都是有效的,直接调用onSizeReady
        onSizeReady(overrideWidth, overrideHeight);
      } else {
        //否则调用target.getSize,并把自身传入,因为SingleRequest实现了SizeReadyCallback,获取成功最终还是回调到onSizeReady方法
        target.getSize(this);
      }

      if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)
          && canNotifyStatusChanged()) {
        target.onLoadStarted(getPlaceholderDrawable());
      }
      if (IS_VERBOSE_LOGGABLE) {
        logV("finished run method in " + LogTime.getElapsedMillis(startTime));
      }
    }
  }

最终都是调用到onSizeReady方法,onSizeReady方法中调用的是engine的load方法,engine是在Glide的建造者中构造的

//SingleRequest.java
public void onSizeReady(int width, int height) {
    stateVerifier.throwIfRecycled();
    synchronized (requestLock) {
      if (IS_VERBOSE_LOGGABLE) {
        logV("Got onSizeReady in " + LogTime.getElapsedMillis(startTime));
      }
      if (status != Status.WAITING_FOR_SIZE) {
        //如果还在等待size结果。直接返回
        return;
      }
      //将status设置为Status.RUNNING
      status = Status.RUNNING;

      float sizeMultiplier = requestOptions.getSizeMultiplier();
      this.width = maybeApplySizeMultiplier(width, sizeMultiplier);
      this.height = maybeApplySizeMultiplier(height, sizeMultiplier);

      if (IS_VERBOSE_LOGGABLE) {
        logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime));
      }
      //调用引擎的load方法加载图片
      loadStatus =
          engine.load(
              glideContext,
              model,
              requestOptions.getSignature(),
              this.width,
              this.height,
              requestOptions.getResourceClass(),
              transcodeClass,
              priority,
              requestOptions.getDiskCacheStrategy(),
              requestOptions.getTransformations(),
              requestOptions.isTransformationRequired(),
              requestOptions.isScaleOnlyOrNoTransform(),
              requestOptions.getOptions(),
              requestOptions.isMemoryCacheable(),
              requestOptions.getUseUnlimitedSourceGeneratorsPool(),
              requestOptions.getUseAnimationPool(),
              requestOptions.getOnlyRetrieveFromCache(),
              this,//传入回调
              callbackExecutor);

      // This is a hack that's only useful for testing right now where loads complete synchronously
      // even though under any executor running on any thread but the main thread, the load would
      // have completed asynchronously.
      if (status != Status.RUNNING) {
        loadStatus = null;
      }
      if (IS_VERBOSE_LOGGABLE) {
        logV("finished onSizeReady in " + LogTime.getElapsedMillis(startTime));
      }
    }
  }

需要注意的是load方法传入了一个ResourceCallback cb参数,这个接口就是加载结果的回调。

public interface ResourceCallback {
  //加载成功
  void onResourceReady(
      Resource<?> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey);
  //加载失败
  void onLoadFailed(GlideException e);

  Object getLock();
}
//Engine.java
public <R> LoadStatus load(...) {
    long startTime = VERBOSE_IS_LOGGABLE ? LogTime.getLogTime() : 0;

    EngineKey key =
        keyFactory.buildKey(
            model,
            signature,
            width,
            height,
            transformations,
            resourceClass,
            transcodeClass,
            options);

    EngineResource<?> memoryResource;
    //加锁,同一时间内只能添加一个加载工作
    synchronized (this) {
      //先重缓存中加载
      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);
      }
    }

    // Avoid calling back while holding the engine lock, doing so makes it easier for callers to
    // deadlock.
    cb.onResourceReady(
        memoryResource, DataSource.MEMORY_CACHE, /* isLoadedFromAlternateCacheKey= */ false);
    return null;
  }

分析缓存加载流程

//Engine.java
private EngineResource<?> loadFromMemory(
      EngineKey key, boolean isMemoryCacheable, long startTime) {
    if (!isMemoryCacheable) {
      return null;
    }
    //先从活跃缓存中加载
    EngineResource<?> active = loadFromActiveResources(key);
    if (active != null) {
      if (VERBOSE_IS_LOGGABLE) {
        logWithTimeAndKey("Loaded resource from active resources", startTime, key);
      }
      return active;
    }

    //活跃缓存没有找到,继续去非活跃缓存中加载
    EngineResource<?> cached = loadFromCache(key);
    if (cached != null) {
      if (VERBOSE_IS_LOGGABLE) {
        logWithTimeAndKey("Loaded resource from cache", startTime, key);
      }
      return cached;
    }
    //都没查到,返回null
    return null;
  }
  

活跃缓存是直接在Map中

private EngineResource<?> loadFromActiveResources(Key key) {
    //ActiveResources的实例,里面存放的是Map<Key, ResourceWeakReference>
    EngineResource<?> active = activeResources.get(key);
    if (active != null) {
      active.acquire();
    }

    return active;
  }

从缓存中加载,缓存对象是Engine构造的时候传入的,最开始在Glide构建时候新建的LruResourceCache,是Glide自己实现的LRU

  private EngineResource<?> loadFromCache(Key key) {
    EngineResource<?> cached = getEngineResourceFromCache(key);
    if (cached != null) {
      cached.acquire();
      activeResources.activate(key, cached);
    }
    return cached;
  }
  
  private EngineResource<?> getEngineResourceFromCache(Key key) {
    Resource<?> cached = cache.remove(key);

    final EngineResource<?> result;
    if (cached == null) {
      result = null;
    } else if (cached instanceof EngineResource) {
      // Save an object allocation if we've cached an EngineResource (the typical case).
      result = (EngineResource<?>) cached;
    } else {
      result =
          new EngineResource<>(
              cached,
              /* isMemoryCacheable= */ true,
              /* isRecyclable= */ true,
              key,
              /* listener= */ this);
    }
    return result;
  }

缓存没有查到,会调用waitForExistingOrStartNewJob方法,等待已经存在的任务或者开启新的任务。

//Engine.java
private <R> LoadStatus waitForExistingOrStartNewJob(...) {
    //先从jobs里面查询是否有加入过
    EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
    if (current != null) {
      current.addCallback(cb, callbackExecutor);
      if (VERBOSE_IS_LOGGABLE) {
        logWithTimeAndKey("Added to existing load", startTime, key);
      }
      //查询到,直接返回LoadStatus,加载的状态
      return new LoadStatus(cb, current);
    }
    //没查到,通过engineJobFactory工厂构建一个新的EngineJob
    EngineJob<R> engineJob =
        engineJobFactory.build(
            key,
            isMemoryCacheable,
            useUnlimitedSourceExecutorPool,
            useAnimationPool,
            onlyRetrieveFromCache);
    //在通过解码job工厂构建一个新的解码job
    DecodeJob<R> decodeJob =
        decodeJobFactory.build(
            glideContext,
            model,
            key,
            signature,
            width,
            height,
            resourceClass,
            transcodeClass,
            priority,
            diskCacheStrategy,
            transformations,
            isTransformationRequired,
            isScaleOnlyOrNoTransform,
            onlyRetrieveFromCache,
            options,
            engineJob);
    //添加到 jobs里面
    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);
  }

下面分析几个点

  • Jobs
  • LoadStatus
  • EngineJob
  • DecodeJob

Jobs

Jobs比较简单,可以理解为就是个工作存储器。有两个Map,

  • jobs 存储普通服务的Map
  • onlyCacheJobs 存储只从缓存取的job的Map
final class Jobs {
  private final Map<Key, EngineJob<?>> jobs = new HashMap<>();
  private final Map<Key, EngineJob<?>> onlyCacheJobs = new HashMap<>();

  @VisibleForTesting
  Map<Key, EngineJob<?>> getAll() {
    return Collections.unmodifiableMap(jobs);
  }

  EngineJob<?> get(Key key, boolean onlyRetrieveFromCache) {
    return getJobMap(onlyRetrieveFromCache).get(key);
  }

  void put(Key key, EngineJob<?> job) {
    getJobMap(job.onlyRetrieveFromCache()).put(key, job);
  }

  void removeIfCurrent(Key key, EngineJob<?> expected) {
    Map<Key, EngineJob<?>> jobMap = getJobMap(expected.onlyRetrieveFromCache());
    if (expected.equals(jobMap.get(key))) {
      jobMap.remove(key);
    }
  }

  private Map<Key, EngineJob<?>> getJobMap(boolean onlyRetrieveFromCache) {
    return onlyRetrieveFromCache ? onlyCacheJobs : jobs;
  }
}

LoadStatus

LoadStatus就更简单了,仅仅是包装了engineJob和cb()回调。并提供了一个cancel方法。所以核心就是可以取消请求。

public class LoadStatus {
    private final EngineJob<?> engineJob;
    private final ResourceCallback cb;

    LoadStatus(ResourceCallback cb, EngineJob<?> engineJob) {
      this.cb = cb;
      this.engineJob = engineJob;
    }

    public void cancel() {
      synchronized (Engine.this) {
        engineJob.removeCallback(cb);
      }
    }
  }

EngineJob

EngineJob虽然叫job但是并没有实现Runnable接口,在start启动了decodeJob

//EngineJob.java
public synchronized void start(DecodeJob<R> decodeJob) {
    this.decodeJob = decodeJob;
    GlideExecutor executor =
        decodeJob.willDecodeFromCache() ? diskCacheExecutor : getActiveSourceExecutor();
    executor.execute(decodeJob);
  }

DecodeJob

EngineJob其实仅仅是对DecodeJob的包裹,真正实现请求的地方在DecodeJob。DecodeJob实现了Runnable接口,由线程执行器调度启动。

//DecodeJob.java
public void run() {
    ...
    DataFetcher<?> localFetcher = currentFetcher;
    try {
      if (isCancelled) {
        notifyFailed();
        return;
      }
      runWrapped();
    ...
    } finally {
      // Keeping track of the fetcher here and calling cleanup is excessively paranoid, we call
      // close in all cases anyway.
      if (localFetcher != null) {
        localFetcher.cleanup();
      }
      GlideTrace.endSection();
    }
  }

下面去看runWrapped方法,runWrapped,又调用了getNextStage方法,这里用到了两个设计模式:责任链模式和策略模式。

runReason,执行任务的原因,三种枚举值:

  • INITIALIZE:第一次调度任务
  • WITCH_TO_SOURCE_SERVICE:本地缓存策略失败,尝试重新获取数据,两种情况;当stage为Stage.SOURCE,或者获取数据失败并且执行和回调发生在了不同的线程
  • DECODE_DATA:获取数据成功,但执行和回调不在同一线程,希望回到自己的线程去处理数据

getNextStage:获取下一步的状态

  • INITIALIZE:初始化状态
  • RESOURCE_CACHE:从缓存资源加载
  • DATA_CACHE:从缓存数据加载
  • SOURCE:从源加载获取
  • ENCODE:加载完成后编码成需要的资源
  • FINISHED:完成

getNextGenerator:获取下一个Generator

  • ResourceCacheGenerator :尝试从修改过的资源缓存中获取,如果缓存未命中,尝试从DATA_CACHE中获取
  • DataCacheGenerator 尝试从未修改过的本地缓存中获取数据,如果缓存未命中则尝试从SourceGenerator中获取
  • SourceGenerator 从原始的资源中获取,可能是服务器,也可能是本地的一些原始资源
//DecodeJob.java
 private void runWrapped() {
    switch (runReason) {
      //首次runReason默认是INITIALIZE
      case INITIALIZE:
        //返回Stage.RESOURCE_CACHE
        stage = getNextStage(Stage.INITIALIZE);
        //
        currentGenerator = getNextGenerator();
        runGenerators();
        break;
      case SWITCH_TO_SOURCE_SERVICE:
        runGenerators();
        break;
      case DECODE_DATA:
        decodeFromRetrievedData();
        break;
      default:
        throw new IllegalStateException("Unrecognized run reason: " + runReason);
    }
  }
  
  private DataFetcherGenerator getNextGenerator() {
    switch (stage) {
      case RESOURCE_CACHE:
        //首次stage为RESOURCE_CACHE返回ResourceCacheGenerator实例
        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);
    }
  }
  
  private Stage getNextStage(Stage current) {
    switch (current) {
      case INITIALIZE:
        //策略模式,根据不同的策略返回不同的结果,默认是ALL那个实例
        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 void runGenerators() {
    currentThread = Thread.currentThread();
    startFetchTime = LogTime.getLogTime();
    boolean isStarted = false;
    //首次currentGenerator为ResourceCacheGenerator
    while (!isCancelled
        && currentGenerator != null
        && !(isStarted = currentGenerator.startNext())) {
      //只要返回的isStarted不是true,就不断的去下一个阶段找
      stage = getNextStage(stage);
      currentGenerator = getNextGenerator();

      if (stage == Stage.SOURCE) {
        //当stage为Stage.SOURCE的时候表示需要去请求数据,这个时候调用reschedule
        reschedule(RunReason.SWITCH_TO_SOURCE_SERVICE);
        return;
      }
    }
    // We've run out of stages and generators, give up.
    if ((stage == Stage.FINISHED || isCancelled) && !isStarted) {
      notifyFailed();
    }

    // Otherwise a generator started a new load and we expect to be called back in
    // onDataFetcherReady.
  }

以上请求对于我们首次加载的网络图片,最终会走到SourceGenerator的startNext()方法,startNext()又调用到startNextLoad()方法

//SourceGenerator.java
public boolean startNext() {
    ...
    sourceCacheGenerator = null;

    loadData = null;
    boolean started = false;
    while (!started && hasNextModelLoader()) {
      loadData = helper.getLoadData().get(loadDataListIndex++);
      if (loadData != null
          && (helper.getDiskCacheStrategy().isDataCacheable(loadData.fetcher.getDataSource())
              || helper.hasLoadPath(loadData.fetcher.getDataClass()))) {
        started = true;
        startNextLoad(loadData);
      }
    }
    return started;
  }
  
  private void startNextLoad(final LoadData<?> toStart) {
    loadData.fetcher.loadData(
        helper.getPriority(),
        new DataCallback<Object>() {
          @Override
          public void onDataReady(@Nullable Object data) {
            if (isCurrentRequest(toStart)) {
              onDataReadyInternal(toStart, data);
            }
          }

          @Override
          public void onLoadFailed(@NonNull Exception e) {
            if (isCurrentRequest(toStart)) {
              onLoadFailedInternal(toStart, e);
            }
          }
        });
  }

这里关于数据加载过程,这里暂时不再深入,后面有时间再深入。最终看回调是到了onDataReadyInternal,

//SourceGenerator.java
void onDataReadyInternal(LoadData<?> loadData, 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. Then once we're back on Glide's thread, we'll
      // get called again and we can write the retrieved data to cache.
      cb.reschedule();
    } else {
      cb.onDataFetcherReady(
          loadData.sourceKey,
          data,
          loadData.fetcher,
          loadData.fetcher.getDataSource(),
          originalKey);
    }
  }

上面如果磁盘缓存策略认为这个资源是可以被缓存的,执行写入磁盘缓存的操作。具体怎么执行的感兴趣的朋友可以看看。有点绕,不过就像方法名起的那样再次执行,多走了一次圈罢了。又回到DecodeJob的onDataFetcherReady将数据解码出来

public void onDataFetcherReady(
      Key sourceKey, Object data, DataFetcher<?> fetcher, DataSource dataSource, Key attemptedKey) {
    this.currentSourceKey = sourceKey;
    this.currentData = data;
    this.currentFetcher = fetcher;
    this.currentDataSource = dataSource;
    this.currentAttemptingKey = attemptedKey;
    this.isLoadingFromAlternateCacheKey = sourceKey != decodeHelper.getCacheKeys().get(0);

    if (Thread.currentThread() != currentThread) {
      reschedule(RunReason.DECODE_DATA);
    } else {
      GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData");
      try {
        decodeFromRetrievedData();
      } finally {
        GlideTrace.endSection();
      }
    }
  }
  
 private void decodeFromRetrievedData() {
    if (Log.isLoggable(TAG, Log.VERBOSE)) {
      logWithTimeAndKey(
          "Retrieved data",
          startFetchTime,
          "data: "
              + currentData
              + ", cache key: "
              + currentSourceKey
              + ", fetcher: "
              + currentFetcher);
    }
    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, isLoadingFromAlternateCacheKey);
    } else {
      runGenerators();
    }
  }
private void notifyEncodeAndRelease(
      Resource<R> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) {
    GlideTrace.beginSection("DecodeJob.notifyEncodeAndRelease");
    try {
      if (resource instanceof Initializable) {
        ((Initializable) resource).initialize();
      }

      Resource<R> result = resource;
      LockedResource<R> lockedResource = null;
      if (deferredEncodeManager.hasResourceToEncode()) {
        lockedResource = LockedResource.obtain(resource);
        result = lockedResource;
      }

      notifyComplete(result, dataSource, isLoadedFromAlternateCacheKey);

      stage = Stage.ENCODE;
      try {
        if (deferredEncodeManager.hasResourceToEncode()) {
          deferredEncodeManager.encode(diskCacheProvider, options);
        }
      } finally {
        if (lockedResource != null) {
          lockedResource.unlock();
        }
      }
      // Call onEncodeComplete outside the finally block so that it's not called if the encode
      // process
      // throws.
      onEncodeComplete();
    } finally {
      GlideTrace.endSection();
    }
  }
  
//通知完成
private void notifyComplete(
      Resource<R> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) {
    setNotifiedOrThrow();
    //最终调用callback的onResourceReady
    callback.onResourceReady(resource, dataSource, isLoadedFromAlternateCacheKey);
  }

这里最终又调用回EngineJob的onResourceReady方法,最终调用到Engine.load方法执行的时候传入的ResourceCallback的onResourceReady。也就是SingleRequest的实现的onResourceReady方法

//EngineJob.java
private class CallResourceReady implements Runnable {

    private final ResourceCallback cb;

    CallResourceReady(ResourceCallback cb) {
      this.cb = cb;
    }

    @Override
    public void run() {
      // Make sure we always acquire the request lock, then the EngineJob lock to avoid deadlock
      // (b/136032534).
      synchronized (cb.getLock()) {
        synchronized (EngineJob.this) {
          if (cbs.contains(cb)) {
            // Acquire for this particular callback.
            engineResource.acquire();
            callCallbackOnResourceReady(cb);
            removeCallback(cb);
          }
          decrementPendingCallbacks();
        }
      }
    }
  }

如何把请求结果显示到ImageView上

前面分析到,请求的结果最终回调到SingleRequest的实现的onResourceReady方法中

public void onResourceReady(
      Resource<?> resource, DataSource dataSource, boolean isLoadedFromAlternateCacheKey) {
    stateVerifier.throwIfRecycled();
    Resource<?> toRelease = null;
    try {
      synchronized (requestLock) {
        loadStatus = null;
        if (resource == null) {
          //resource为空,抛异常
          GlideException exception =new GlideException(...);
          onLoadFailed(exception);
          return;
        }

        Object received = resource.get();
        if (received == null || !transcodeClass.isAssignableFrom(received.getClass())) {
          toRelease = resource;
          this.resource = null;
          //抛异常
          GlideException exception =new GlideException(...);
          onLoadFailed(exception);
          return;
        }

        if (!canSetResource()) {
          toRelease = resource;
          this.resource = null;
          // We can't put the status to complete before asking canSetResource().
          status = Status.COMPLETE;
          GlideTrace.endSectionAsync(TAG, cookie);
          return;
        }
        //调用复写的onResourceReady方法
        onResourceReady(
            (Resource<R>) resource, (R) received, dataSource, isLoadedFromAlternateCacheKey);
      }
    } finally {
      if (toRelease != null) {
        engine.release(toRelease);
      }
    }
  }
private void onResourceReady(
      Resource<R> resource, R result, DataSource dataSource, boolean isAlternateCacheKey) {
    // We must call isFirstReadyResource before setting status.
    boolean isFirstResource = isFirstReadyResource();
    status = Status.COMPLETE;
    this.resource = resource;
    ...
    notifyRequestCoordinatorLoadSucceeded();

    isCallingCallbacks = true;
    try {
      boolean anyListenerHandledUpdatingTarget = false;
      if (requestListeners != null) {
        for (RequestListener<R> listener : requestListeners) {
          anyListenerHandledUpdatingTarget |=
              listener.onResourceReady(result, model, target, dataSource, isFirstResource);

          if (listener instanceof ExperimentalRequestListener) {
            ExperimentalRequestListener<R> experimentalRequestListener =
                (ExperimentalRequestListener<R>) listener;
            anyListenerHandledUpdatingTarget |=
                experimentalRequestListener.onResourceReady(
                    result, model, target, dataSource, isFirstResource, isAlternateCacheKey);
          }
        }
      }
      anyListenerHandledUpdatingTarget |=
          targetListener != null
              && targetListener.onResourceReady(result, model, target, dataSource, isFirstResource);

      if (!anyListenerHandledUpdatingTarget) {
        Transition<? super R> animation = animationFactory.build(dataSource, isFirstResource);
        //调用target的onResourceReady方法
        target.onResourceReady(result, animation);
      }
    } finally {
      isCallingCallbacks = false;
    }

    GlideTrace.endSectionAsync(TAG, cookie);
  }
//ImageViewTarget.java
 public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {
    if (transition == null || !transition.transition(resource, this)) {
      setResourceInternal(resource);
    } else {
      maybeUpdateAnimatable(resource);
    }
  }
  
private void setResourceInternal(@Nullable Z resource) {
    // Order matters here. Set the resource first to make sure that the Drawable has a valid and
    // non-null Callback before starting it.
    setResource(resource);
    maybeUpdateAnimatable(resource);
  }
  
protected abstract void setResource(@Nullable Z resource);

还记得上面target的构造过程吗,ImageViewTarget有几个实现类,其中就是BitmapImageViewTarget和DrawableImageViewTarget,这里构建的是BitmapImageViewTarget, 我们看下setResource的实现

protected void setResource(Bitmap resource) {
    //最终调用View的setImageBitmap方法
    view.setImageBitmap(resource);
  }

如何感知生命周期

还记得前面RequestManager构造的时候有三种情况,context,FragmentActivity,Fragment。对于FragmentActivity,Fragment,构造的时候会分别传入activity.getLifecycle(),fragment.getLifecycle()。

RequestManager getOrCreate(
      Context context,
      Glide glide,
      final Lifecycle lifecycle,
      FragmentManager childFragmentManager,
      boolean isParentVisible) {
    Util.assertMainThread();
    RequestManager result = getOnly(lifecycle);
    if (result == null) {
      //先生成一个LifecycleLifecycle把上面传进来的Lifecycle作为参数
      LifecycleLifecycle glideLifecycle = new LifecycleLifecycle(lifecycle);
      result =
          factory.build(
              glide,
              glideLifecycle,
              new SupportRequestManagerTreeNode(childFragmentManager),
              context);
      lifecycleToRequestManager.put(lifecycle, result);
      glideLifecycle.addListener(
          new LifecycleListener() {
            @Override
            public void onStart() {}

            @Override
            public void onStop() {}

            @Override
            public void onDestroy() {
              lifecycleToRequestManager.remove(lifecycle);
            }
          });
      // This is a bit of hack, we're going to start the RequestManager, but not the
      // corresponding Lifecycle. It's safe to start the RequestManager, but starting the
      // Lifecycle might trigger memory leaks. See b/154405040
      if (isParentVisible) {
        result.onStart();
      }
    }
    return result;
  }

LifecycleLifecycle比较简单,就是新建了一个Set lifecycleListeners,然后addListener的时候把传进来的LifecycleListener存储到lifecycleListeners里面。LifecycleLifecycle构造方法中会把本身绑定到Android系统的androidx.lifecycle.Lifecycle监听

final class LifecycleLifecycle implements Lifecycle, LifecycleObserver {
  @NonNull
  private final Set<LifecycleListener> lifecycleListeners = new HashSet<LifecycleListener>();

  @NonNull private final androidx.lifecycle.Lifecycle lifecycle;

  LifecycleLifecycle(androidx.lifecycle.Lifecycle lifecycle) {
    this.lifecycle = lifecycle;
    lifecycle.addObserver(this);
  }

  @OnLifecycleEvent(Event.ON_START)
  public void onStart(@NonNull LifecycleOwner owner) {
    //通知所有的LifecycleListener,Util.getSnapshot是为了线程安全,每次都copy出一份
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
      lifecycleListener.onStart();
    }
  }

  @OnLifecycleEvent(Event.ON_STOP)
  public void onStop(@NonNull LifecycleOwner owner) {
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
      lifecycleListener.onStop();
    }
  }

  @OnLifecycleEvent(Event.ON_DESTROY)
  public void onDestroy(@NonNull LifecycleOwner owner) {
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
      lifecycleListener.onDestroy();
    }
    owner.getLifecycle().removeObserver(this);
  }

  @Override
  public void addListener(@NonNull LifecycleListener listener) {
    lifecycleListeners.add(listener);

    if (lifecycle.getCurrentState() == State.DESTROYED) {
      listener.onDestroy();
    } else if (lifecycle.getCurrentState().isAtLeast(State.STARTED)) {
      listener.onStart();
    } else {
      listener.onStop();
    }
  }

  @Override
  public void removeListener(@NonNull LifecycleListener listener) {
    lifecycleListeners.remove(listener);
  }
}
RequestManager(...) {
    ...
    if (Util.isOnBackgroundThread()) {
      Util.postOnUiThread(addSelfToLifecycle);
    } else {
      //这里将RequestManager实例添加到lifecycle的监听器集合中
      lifecycle.addListener(this);
    }
    ...
  }

如何监控网络变化

前面分析监控生命周期的时候,注意到一个connectivityMonitor也被添加到生命周期监控集合中

RequestManager(...) {
    ...
    connectivityMonitor =
        factory.build(
            context.getApplicationContext(),
            new RequestManagerConnectivityListener(requestTracker));
    ...
    
    //这里将connectivityMonitor添加到lifecycle的监听器集合中
    lifecycle.addListener(connectivityMonitor);
    ...
  }

ConnectivityMonitorFactory的实现只有一个DefaultConnectivityMonitorFactory,我们去看它的build方法

public class DefaultConnectivityMonitorFactory implements ConnectivityMonitorFactory {
  private static final String TAG = "ConnectivityMonitor";
  private static final String NETWORK_PERMISSION = "android.permission.ACCESS_NETWORK_STATE";

  @NonNull
  @Override
  public ConnectivityMonitor build(
      @NonNull Context context, @NonNull ConnectivityMonitor.ConnectivityListener listener) {
    int permissionResult = ContextCompat.checkSelfPermission(context, NETWORK_PERMISSION);
    boolean hasPermission = permissionResult == PackageManager.PERMISSION_GRANTED;
    ...
    return hasPermission
        ? new DefaultConnectivityMonitor(context, listener)
        : new NullConnectivityMonitor();
  }
}

这里主要新建了一个DefaultConnectivityMonitor,因为NullConnectivityMonitor是没有权限的时候才去新建的,方法都是空实现。

final class DefaultConnectivityMonitor implements ConnectivityMonitor {
  private final Context context;

  @SuppressWarnings("WeakerAccess")
  @Synthetic
  final ConnectivityListener listener;

  DefaultConnectivityMonitor(@NonNull Context context, @NonNull ConnectivityListener listener) {
    this.context = context.getApplicationContext();
    this.listener = listener;
  }

  private void register() {
    SingletonConnectivityReceiver.get(context).register(listener);
  }

  private void unregister() {
    SingletonConnectivityReceiver.get(context).unregister(listener);
  }

  @Override
  public void onStart() {
    register();
  }

  @Override
  public void onStop() {
    unregister();
  }

  @Override
  public void onDestroy() {
    // Do nothing.
  }
}

核心就是在onStart()注册一个监听,在onStop()取消注册监听。SingletonConnectivityReceiver是个单例模式实现的网络状态监听器。

final class SingletonConnectivityReceiver {
  private static volatile SingletonConnectivityReceiver instance;
  

  @GuardedBy("this")
  @Synthetic
  final Set<ConnectivityListener> listeners = new HashSet<ConnectivityListener>();

  //单例模式实现SingletonConnectivityReceiver
  static SingletonConnectivityReceiver get(@NonNull Context context) {
    if (instance == null) {
      synchronized (SingletonConnectivityReceiver.class) {
        if (instance == null) {
          instance = new SingletonConnectivityReceiver(context.getApplicationContext());
        }
      }
    }
    return instance;
  }


  private SingletonConnectivityReceiver(final @NonNull Context context) {
    GlideSupplier<ConnectivityManager> connectivityManager =
        GlideSuppliers.memorize(
            new GlideSupplier<ConnectivityManager>() {
              @Override
              public ConnectivityManager get() {
                return (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
              }
            });
    ConnectivityListener connectivityListener =
        new ConnectivityListener() {
          @Override
          public void onConnectivityChanged(boolean isConnected) {
            //网络状态发生变化的时候通知所有的listeners
            Util.assertMainThread();
            List<ConnectivityListener> toNotify;
            synchronized (SingletonConnectivityReceiver.this) {
              toNotify = new ArrayList<>(listeners);
            }
            for (ConnectivityListener listener : toNotify) {
              listener.onConnectivityChanged(isConnected);
            }
          }
        };

    frameworkConnectivityMonitor =
        Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
            ? new FrameworkConnectivityMonitorPostApi24(connectivityManager, connectivityListener)
            : new FrameworkConnectivityMonitorPreApi24(
                context, connectivityManager, connectivityListener);
  }

  synchronized void register(ConnectivityListener listener) {
    listeners.add(listener);
    maybeRegisterReceiver();
  }

  /**
   * To avoid holding a lock while notifying listeners, the unregistered listener may still be
   * notified about a connectivity change after this method completes if this method is called on a
   * thread other than the main thread and if a connectivity broadcast is racing with this method.
   * Callers must handle this case.
   */
  synchronized void unregister(ConnectivityListener listener) {
    listeners.remove(listener);
    maybeUnregisterReceiver();
  }

  ...
}

用到哪些设计模式

  • 单例模式
  • 建造者模式
  • 外观模式
  • 享元模式
  • 原型模式
  • 观察者模式
  • 简单工厂
  • 工厂方法
  • 责任链模式
  • 策略模式

参考链接

https://juejin.cn/post/7044079102839488543?searchId=202410100927002AB04F7243D94B6586AA
https://blog.csdn.net/Love667767/article/details/106576888/
https://www.cnblogs.com/android-blogs/p/5735655.htmlun

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2246987.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

TransFormer--整合编码器和解码器

TransFormer--整合编码器和解码器 下图完整地展示了带有编码器和解码器的Transformer架构。 在图中&#xff0c;N表示可以堆叠N个编码器和解码器。我们可以看到&#xff0c;一旦输入句子&#xff08;原句&#xff09;&#xff0c;编码器就会学习其特征并将特征发送给解码器&…

短视频矩阵矩阵,矩阵号策略

随着数字媒体的迅猛发展&#xff0c;短视频平台已经成为企业和个人品牌推广的核心渠道。在这一背景下&#xff0c;短视频矩阵营销策略应运而生&#xff0c;它通过高效整合和管理多个短视频账号&#xff0c;实现资源的最优配置和营销效果的最大化。本文旨在深入探讨短视频矩阵的…

Apple Vision Pro开发002-新建项目配置

一、新建项目 可以选择默认的&#xff0c;也可以选择Universal 3D 二、切换打包平台 注意选择Target SDK为Devices SDk&#xff0c;这种适配打包到真机调试 三、升级新的Input系统 打开ProjectSettings&#xff0c;替换完毕之后引擎会重启 四、导入PolySpatial 修改上图红…

【StarRocks】starrocks 3.2.12 【share-nothing】 多Be集群容器化部署

文章目录 一. 集群规划二.docker compose以及启动脚本卷映射对于网络环境变量 三. 集群测试用户新建、赋权、库表初始化断电重启扩容 BE 集群 一. 集群规划 部署文档 https://docs.starrocks.io/zh/docs/2.5/deployment/plan_cluster/ 分类描述FE节点1. 主要负责元数据管理、…

LLaMA-Factory 上手即用教程

LLaMA-Factory 是一个高效的大型语言模型微调工具&#xff0c;支持多种模型和训练方法&#xff0c;包括预训练、监督微调、强化学习等&#xff0c;同时提供量化技术和实验监控&#xff0c;旨在提高训练速度和模型性能。 官方开源地址&#xff1a;https://github.com/hiyouga/L…

Java基础面试题01-请描述Java中JDK和JRE的区别?

什么是 JDK&#xff1f; JDK 全称 Java Development Kit&#xff0c;中文叫“Java 开发工具包”。 它是给 Java 开发者用的工具箱&#xff0c;里面有一切写代码、编译代码、调试代码所需要的工具。 JDK 包括什么&#xff1f; Java 编译器&#xff08;javac&#xff09;&…

Ubuntu20.04下安装向日葵

向日葵远程控制app官方下载 - 贝锐向日葵官网 下载Ununtu版的图形版本的安装deb包SunloginClient_15.2.0.63064_amd64.deb 直接执行 sudo dpkg -i SunloginClient_15.2.0.63064_amd64.deb 的话会报错: 如果在Ubuntu20.04里直接执行sudo apt install libgconf-2-4安装libgco…

Typora+PicGo+云服务器搭建博客图床

文章目录 前言一. 为什么要搭建博客图床&#xff1f;1.1 什么是图床&#xff1f;1.2 为什么要搭建博客图床? 二. 安装软件三. 配置阿里云OSS3.1 注册,开通对象储存3.2 创建bucket3.3 找到你的地域节点3.4 accessKeyId和accessKeySecret3.5 给你的阿里云账户充值 四. 配置4.1 配…

Python的3D可视化库 - vedo (2)visual子模块 基本可视化行为

文章目录 1. visual模块的继承关系2. 基类CommonVisual的方法2.1 获取对象信息2.1.1 对象本身信息2.1.2 对象的查找表2.1.3 对象标量范围2.1.4 对象缩略图 2.2 呈现对象2.2.1 在窗口显示1.2.2 对象可见性 2.2.3 对象颜色2.2.4 对象透明度 2.3 添加标度条2.3.1 2D标度条2.3.2 3D…

常用Rust日志处理工具教程

在本文中&#xff0c;我想讨论Rust中的日志。通过一些背景信息&#xff0c;我将带您了解两个日志库&#xff1a;env_logger和log4rs。最后&#xff0c;我将分享我的建议和github的片段。 Rust log介绍 log包是Rust中日志API的事实标准&#xff0c;共有五个日志级别&#xff1…

废品买卖回收管理系统|Java|SSM|Vue| 前后端分离

【重要①】前后端源码万字文档部署文档 【重要②】正版源码有问题包售后 【包含内容】 【一】项目提供非常完整的源码注释 【二】相关技术栈文档 【三】源码讲解视频 【其它服务】 【一】可以提供远程部署安装&#xff0c;包扩环境 【…

案例研究|阿特斯的JumpServer分布式部署和多组织管理实践

苏州阿特斯阳光电力科技有限公司&#xff08;以下简称为阿特斯&#xff09;是一家集太阳能光伏组件制造和为全球客户提供太阳能应用产品研发、设计、制造、销售的专业公司。 阿特斯集团总部位于加拿大&#xff0c;中国区总部位于江苏省苏州市。通过全球战略和多元化的市场布局…

tongweb安全整改

一 禁止以root账号运行tongweb服务 1 如果是首次安装须创建普通用户安装tongweb 2 如果已经使用root账号安装了tongweb 2.1 创建普通用户 2.2 使用root账号授予tongweb安装目录宿主权限为普通用户 2.3赋权成功后&#xff0c;后续启动tongweb服务必须为普通用户 二 tongRDS隐…

快速识别模型:simple_ocr,部署教程

快速识别图片中的英文、标点符号、数学符号、Emoji, 模型会输出图片中文字行的坐标位置、最低得分、识别结果。当前服务用到的模型&#xff1a;检测模型、数字识别、英文符号识别。 一、部署流程 1.更新基础环境 apt update2.安装miniconda wget https://repo.anaconda.com/…

tcpdump抓包 wireShark

TCPdump抓包工具介绍 TCPdump&#xff0c;全称dump the traffic on anetwork&#xff0c;是一个运行在linux平台可以根据使用者需求对网络上传输的数据包进行捕获的抓包工具。 tcpdump可以支持的功能: 1、在Linux平台将网络中传输的数据包全部捕获过来进行分析 2、支持网络层…

HarmonyOS4+NEXT星河版入门与项目实战(11)------Button组件

文章目录 1、控件图解2、案例实现1、代码实现2、代码解释3、运行效果4、总结1、控件图解 这里我们用一张完整的图来汇整 Button 的用法格式、属性和事件,如下所示: 按钮默认类型就是胶囊类型。 2、案例实现 这里我们实现一个根据放大和缩小按钮来改变图片大小的功能。 功…

YOLOV5 /onnx模型转换成rknn

上两篇文章讲述了pytorch模型下best.pt转换成onnx模型&#xff0c;以及将onnx进行简化成为best-sim.onnx, 接下来这篇文章讲述如何将onnx模型转换成rknn模型&#xff0c;转换成该模型是为了在rk3568上运行 1.创建share文件夹 文件夹包含以下文件best-sim.onnx,rknn-tookit2-…

【51单片机】LCD1602液晶显示屏

学习使用的开发板&#xff1a;STC89C52RC/LE52RC 编程软件&#xff1a;Keil5 烧录软件&#xff1a;stc-isp 开发板实图&#xff1a; 文章目录 LCD1602存储结构时序结构 编码 —— 显示字符、数字 LCD1602 LCD1602&#xff08;Liquid Crystal Display&#xff09;液晶显示屏是…

如何使用AWS Lambda构建一个云端工具(超详细)

首发地址&#xff08;欢迎大家访问&#xff09;&#xff1a;如何使用AWS Lambda构建一个云端工具&#xff08;超详细&#xff09; 1 前言 1.1 无服务器架构 无服务器架构&#xff08;Serverless Computing&#xff09;是一种云计算服务模型&#xff0c;它允许开发者构建和运行…

【Isaac Sim】相关问题汇总

目录 一、安装点击Install时报错二、启动时报 Failed to create any GPU devices三、加载Isaac Sim自带模型或示例时报 Isaac Sim is not responding 一、安装点击Install时报错 报错&#xff1a; request to https://asset.launcher.omniverse.nvidia.com/… failed, reason:…