Android深入了解Glide

什么是Glide?

Glide 是Android开源控件,是 Android 在开发中广泛使用的图片加载和缓存库。

为什么用Glide?

因为Glide简化 Android 应用中的图片加载过程,提供高效、流畅的用户体验。以下是 Android Glide 的一些主要特点和优势:

主要特点:

1.简单易用:

Glide 提供了直观且易于使用的 API,使得开发者能够快速地加载和显示图片,而无需担心复杂的图片处理逻辑。

例如:

1.1、不用Glide可能需要这样加载图片

// Kotlin 代码示例:不使用 Glide  
  
// 假设你有一个 ImageView 和一个图片的 URL  
val imageView: ImageView = findViewById(R.id.imageView)  
val imageUrl: String = "http://example.com/image.jpg"  
  
// 使用 AsyncTask 来异步加载图片  
AsyncTask.execute(Runnable {  
    // 在后台线程中下载图片  
    val imageBitmap: Bitmap? = downloadImage(imageUrl)  
  
    // 将结果切换回 UI 线程  
    runOnUiThread {  
        // 在 UI 线程中设置 ImageView 的图片  
        imageView.setImageBitmap(imageBitmap)  
    }  
})  
  
// 模拟的图片下载函数,实际开发中应使用合适的网络库如 OkHttp, Retrofit 等  
private fun downloadImage(url: String): Bitmap? {  
    // 实现图片下载和解码的逻辑  
    // 这里省略了实际的下载代码  
    return null // 返回下载并解码后的 Bitmap,或者为 null 表示下载失败  
}

2、使用Glide加载图片

// Kotlin 代码示例:使用 Glide  
  
// 假设你有一个 ImageView 和一个图片的 URL  
val imageView: ImageView = findViewById(R.id.imageView)  
val imageUrl: String = "http://example.com/image.jpg"  
  
// 使用 Glide 加载图片  
Glide.with(this)  
    .load(imageUrl)  
    .into(imageView)  
  
// 无需关心下载、解码和缓存的细节,Glide 会自动处理

从上述两个例子中可以看出,相比之下,使用 Glide 大大简化了代码,仅仅三行则可以。你不需要担心线程管理、图片解码或缓存。

1.2、使用Glide加载图片

//使用 Glide  
  
// 假设你有一个 ImageView 和一个图片的 URL  
val imageView: ImageView = findViewById(R.id.imageView)  
val imageUrl: String = "http://example.com/image.jpg"  
  
// 使用 Glide 加载图片  
Glide.with(this)  
    .load(imageUrl)  
    .into(imageView)  
  
// 无需关心下载、解码和缓存的细节,Glide 会自动处理

从上述两个例子中可以看出,相比之下,使用 Glide 大大简化了代码,仅仅三行则可以加载出图片到View中。而且不需要担心线程管理、图片解码或缓存

** ## 2.高效性能 :
以下我会从几方面解释Glide为什么高效

1 异步加载:

Glide 使用后台线程异步加载图片,从而避免阻塞 UI 线程。这确保了应用的流畅性和响应性,尤其是在加载大量图片或处理大图时。

2 缓存管理:

内置了强大的缓存机制,包括内存缓存和磁盘缓存。内存缓存可以快速提供之前加载过的图片,而磁盘缓存则可以在应用重新启动后或网络不可用时提供图片。
Glide 会根据图片的大小和访问频率智能地管理缓存,以减少重复加载和下载的开销。

3 图片解码与缩放:

Glide 也是使用Android原生代码进行图片解码,以最大限度地减少内存占用和计算开销。它会根据设备的屏幕密度和 ImageView 的尺寸智能地调整图片的大小和质量,避免加载过大或过小的图片。

4 生命周期管理:

Glide 紧密集成 Android 生命周期,可以感知 Activity 和 Fragment 的生命周期,自动暂停和恢复图片加载。这确保了图片加载与应用的生命周期保持一致,避免了不必要的资源消耗。

5 网络优化:

Glide 可以与流行的网络库(如 OkHttp)集成,利用这些库提供的连接池、重试机制等功能,进一步提高网络请求的性能。

3.生命周期管理:(正片来袭 Glide版本4.15.1)

Glide 能够感知到 Context(如 Activity 或 Fragment)的生命周期。这意味着当 Activity 或 Fragment 被暂停或销毁时,Glide 会相应地暂停或取消图片加载,从而避免了不必要的资源消耗。
首先是Glide的简单使用:

Glide.with(context)
	 .load("http://example.com/image.jpg")
	 .into(imageView);

这里使用的设计模式 : 建造者设计模式
下面我们根据源码来分析下:

1、with()获取RequestManager

 @NonNull
  public static RequestManager with(@NonNull Context context) {
    return getRetriever(context).get(context);
  }
//with还支持传入 Activity、FragmentActivity、Fragment、android.app.Fragment
//但是官方不建议activity,建议传入FragmentActivity或者androidx.appcompat.app.AppCompatActivity)

2、检测context的合法性,还有就是获取Glide。

  @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,
        "You cannot start a load on a not yet attached View or a Fragment where getActivity() "
            + "returns null (which usually occurs when getActivity() is called before the Fragment "
            + "is attached or after the Fragment is destroyed).");
    return Glide.get(context).getRequestManagerRetriever();
  }

3、获取单例Glide

//通过双重检测机制获得一个单例Glide
  public static Glide get(@NonNull Context context) {
    if (glide == null) {
      GeneratedAppGlideModule annotationGeneratedModule =
          getAnnotationGeneratedGlideModules(context.getApplicationContext());
      synchronized (Glide.class) {
        if (glide == null) {
          checkAndInitializeGlide(context, annotationGeneratedModule);
        }
      }
    }
    return glide;
  }
3.1 检测和初始化Glide
  static void checkAndInitializeGlide(
      @NonNull Context context, @Nullable GeneratedAppGlideModule generatedAppGlideModule) {
    // In the thread running initGlide(), one or more classes may call Glide.get(context).
    // 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 {
      //初始化Glide
      initializeGlide(context, generatedAppGlideModule);
    } finally {
      isInitializing = false;
    }
  }

3.2 初始化Glide

从下面代码,我们可以看到Glide从builder.build函数创建出来后,就放到一个全局静态变量上。

  private static volatile Glide glide;
  ...
  private static void initializeGlide(
      @NonNull Context context,
      @NonNull GlideBuilder builder,
      @Nullable GeneratedAppGlideModule annotationGeneratedModule) {
	... //我们只看Glide创建的,其他先忽略
    Glide glide = builder.build(applicationContext, manifestModules, annotationGeneratedModule);
    ...
    Glide.glide = glide;
  }
3.2.1 builder.build函数
 @NonNull
  Glide build(
      @NonNull Context context,
      List<GlideModule> manifestModules,
      AppGlideModule annotationGeneratedGlideModule) {
  	...
  	... 
    RequestManagerRetriever requestManagerRetriever =
        new RequestManagerRetriever(requestManagerFactory, experiments);

    return new Glide(
        context, //应用程序的上下文
        engine,  //图片加载引擎,这是负责实际图片加载和缓存
        memoryCache, //内存缓存
        bitmapPool, //bitmap池,用于重用和回收不再需要的位图,以减少内存使用和分配次数
        arrayPool, //数组池。用于管理内存中的数组,提高内存使用效率
        requestManagerRetriever, //求管理器检索器。用于获取与特定上下文相关的 RequestManager 实例
        connectivityMonitorFactory, //连接监控器工厂。用于监控网络连接状态,影响图片加载策略。
        logLevel,//日志级别
        defaultRequestOptionsFactory, //默认请求选项工厂。用于创建默认的 RequestOptions,这些选项可以应用于所有的图片加载请求
        defaultTransitionOptions, //默认过渡选项。定义图片加载时的过渡动画
        defaultRequestListeners, //默认请求监听器。允许你监听图片加载过程中的各种事件,如开始加载、加载成功、加载失败等
        manifestModules, //清单模块。这是一个列表,包含所有需要在 Glide 初始化时注册的模块。
        annotationGeneratedGlideModule, //注解生成的 Glide 模块。这通常是用于集成 Glide 和其他库或框架的自动生成的代码。
        experiments);
        //从传入的信息可以看出,创建一个 Glide 的实例配置了多种参数。然后我们就获取了一个Glide实例
        
  }

4、Glide创建后,我们看到RequestManager(Appplication)

下面代码我们可以看到,我们如果调用的时候是主线程,则会使用我们传入的context,如果不是则会去获取ApplicationContext,这是我们使用的时候不用担心是否为主线程的原因。

  @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)) { //检测是否为主线程和是否为Application的context
      if (context instanceof FragmentActivity) {
        return get((FragmentActivity) context);
      } else if (context instanceof Activity) {
        return get((Activity) 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);
  }
4.1 RequestManager的创建

从下述代码不难看出,如果传入的是applicationContext则这个Glide会把资源保留,根据application的生命周期走,所以当我们使用的时候要注意不要传入applicationContext。

  private RequestManager getApplicationManager(@NonNull Context context) {
    // Either an application context or we're on a background thread.
    if (applicationManager == null) {
      synchronized (this) {
        if (applicationManager == null) {
          // Normally pause/resume is taken care of by the fragment we add to the fragment or
          // activity. However, in this case since the manager attached to the application will not
          // receive lifecycle events, we must force the manager to start resumed using
          // ApplicationLifecycle.

          // TODO(b/27524013): Factor out this Glide.get() call.
          Glide glide = Glide.get(context.getApplicationContext());
          applicationManager =
              factory.build(
                  glide,
                  new ApplicationLifecycle(), //Application的生命周期
                  new EmptyRequestManagerTreeNode(),
                  context.getApplicationContext());
        }
      }
    }
4.2 绑定生命周期
  private final Runnable addSelfToLifecycle =
      new Runnable() {
        @Override
        public void run() {
          //生命周期注册
          lifecycle.addListener(RequestManager.this);
        }
      };
  ...
  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());
  }
4.3 生命周期绑定后

生命周期绑定后,则拿activtiy举例,
当Activiy生命周期到onstart时候,则开始发起请求获取图片。
当onstop的时候开始停止获取图片
onDestroy的时候取消请求

  /**
   * Lifecycle callback that registers for connectivity events (if the
   * android.permission.ACCESS_NETWORK_STATE permission is present) and restarts failed or paused
   * requests.
   */
  @Override
  public synchronized void onStart() {
    resumeRequests();
    targetTracker.onStart();
  }

  /**
   * Lifecycle callback that unregisters for connectivity events (if the
   * android.permission.ACCESS_NETWORK_STATE permission is present) and pauses in progress loads.
   */
  @Override
  public synchronized void onStop() {
    pauseRequests();
    targetTracker.onStop();
  }

  /**
   * Lifecycle callback that cancels all in progress requests and clears and recycles resources for
   * all completed requests.
   */
  @Override
  public synchronized void onDestroy() {
    targetTracker.onDestroy();
    for (Target<?> target : targetTracker.getAll()) {
      clear(target);
    }
    targetTracker.clear();
    requestTracker.clearRequests();
    lifecycle.removeListener(this);
    lifecycle.removeListener(connectivityMonitor);
    Util.removeCallbacksOnUiThread(addSelfToLifecycle);
    glide.unregisterRequestManager(this);
  }

4、Glide创建后,我们看到RequestManager(activity、fragment、view)

当context是activity、fragment、view的时候,都会走到fragmentGet的函数
并且传入它的fragmentMnager

  @NonNull
  public RequestManager get(@NonNull Activity activity) {
    if (Util.isOnBackgroundThread()) {
      return get(activity.getApplicationContext());
    } else if (activity instanceof FragmentActivity) {
      return get((FragmentActivity) activity);
    } else {
      assertNotDestroyed(activity);
      frameWaiter.registerSelf(activity);
      android.app.FragmentManager fm = activity.getFragmentManager();
      return fragmentGet(activity, fm, /* parentHint= */ null, isActivityVisible(activity));
    }
  }
4.1将传入的fragmentManager传入

首先,通过传入的activity引用,获取当前页面的FragmentManager,然后将当前页面的引用和刚生成的FragmentManager对象引用,作为参数一起传入fragmentGet(activity, fm)方法。下面看下fragmentGet(activity, fm)的具体实现:

  @NonNull
  private RequestManager fragmentGet(
      @NonNull Context context,
      @NonNull android.app.FragmentManager fm,
      @Nullable android.app.Fragment parentHint,
      boolean isParentVisible) {
    // 基于当前activity注册无UI的RequestManagerFragment
    RequestManagerFragment current = getRequestManagerFragment(fm, parentHint);
    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);
      // 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) {
        requestManager.onStart();
      }
      current.setRequestManager(requestManager);
    }
    return requestManager;
  }

getRequestManagerFragment()做了什么?
生成了一个空白的fragment

  @NonNull
  private RequestManagerFragment getRequestManagerFragment(
      @NonNull final android.app.FragmentManager fm, @Nullable android.app.Fragment parentHint) {
    // If we have a pending Fragment, we need to continue to use the pending Fragment. Otherwise
    // there's a race where an old Fragment could be added and retrieved here before our logic to
    // add our pending Fragment notices. That can then result in both the pending Fragmeng and the
    // old Fragment having requests running for them, which is impossible to safely unwind.
    RequestManagerFragment current = pendingRequestManagerFragments.get(fm);
    if (current == null) {
      current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
      if (current == null) {
        current = new RequestManagerFragment();
        current.setParentFragmentHint(parentHint);
        pendingRequestManagerFragments.put(fm, current);
        fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
        handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
      }
    }
    return current;
  }

RequestManagerFragment生成后会同时初始化lifeCycle

  public RequestManagerFragment() {
    this(new ActivityFragmentLifecycle());
  }

  @VisibleForTesting
  @SuppressLint("ValidFragment")
  RequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) {
    this.lifecycle = lifecycle;
  }
4.2 生成lifecycle后,会在factory.build传入 current.getGlideLifecycle(),然后绑定流程和4.2开始一致
 @NonNull
  private RequestManager fragmentGet(
      @NonNull Context context,
      @NonNull android.app.FragmentManager fm,
      @Nullable android.app.Fragment parentHint,
      boolean isParentVisible) {
    // 基于当前activity注册无UI的RequestManagerFragment
    RequestManagerFragment current = getRequestManagerFragment(fm, parentHint);
    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);
      // 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) {
        requestManager.onStart();
      }
      current.setRequestManager(requestManager);
    }
    return requestManager;
  }

下面是上面用到的主要类的工作内容

RequestManagerRetriever
RequestManagerRetriever是一个中间类,负责获取RequestManager实例。在大多数情况下,它会与Activity或Fragment的生命周期绑定,确保RequestManager的正确创建和销毁。当需要加载图片时,Glide库会通过RequestManagerRetriever获取RequestManager实例,以便管理图片加载请求。

RequestManagerFragment
RequestManagerFragment是一个无UI的Fragment,它内部持有一个RequestManager实例。
当与Activity或Fragment绑定时,RequestManagerFragment能够感知其宿主的生命周期,并在适当的时候调用RequestManager的方法来暂停、恢复或清除请求。

RequestManager
RequestManager是Glide库中用于管理图片加载请求的核心类。
它实现了LifeCycleListener接口,这意味着它可以响应宿主(通常是Activity或Fragment)的生命周期事件。RequestManager提供了如pauseRequests(), resumeRequests(), clearRequests()等方法,以根据宿主的生命周期状态管理图片加载请求。

LifeCycleListener
LifeCycleListener是一个接口,它定义了生命周期管理方法,如onStart(), onStop(), 和onDestroy()。
任何实现了这个接口的类都需要提供这些方法的具体实现,以便在宿主的生命周期事件发生时得到通知。

ActivityFragmentLifecycle
ActivityFragmentLifecycle是一个管理Fragment和RequestManager映射关系的类。
它可能还负责管理LifecycleListener的注册和注销,确保在Fragment的生命周期事件发生时,相应的RequestManager能够得到通知并作出相应的操作。空白Fragment(通常是一个不展示UI的Fragment)会回调这些方法,以便RequestManager可以适当地暂停和恢复图片加载请求。

强大的缓存策略:

Glide内置了强大的缓存机制,包括内存缓存和磁盘缓存。它可以根据设备的可用内存和存储空间智能地管理缓存,以确保图片的快速加载和节省流量。

Glide 主要分两大类 内存缓存磁盘缓存

内存缓存 —— 防止应用重复将图片数据读取到内存当中

磁盘缓存 —— 防止应用重复从网络或其他地方重复下载和读取数据。

这两大缓存还有继续细分为这四类:

活动缓存 : 当前正在被应用使用的图片资源

LRU缓存 : 已经加载但当前不在屏幕上显示的图片的内存 (遵循最近最少使用算法)

资源缓存 : 已经解码并准备好用于显示的图片资源

原始缓存 : 原始的图片数据,即未经解码或修改的图片数据

在这里插入图片描述
Glide 的缓存策略 我们主要关注内存缓存和磁盘缓存这两大类就
我们知道缓存就是把东西存放到一个地方,然后等到我们用的时候就会从这个地方拿出来,那我们怎么去把我们之前存放的东西拿出来呢?

就好像我们去游泳前,会在储物柜放东西,等我们走的时候再从储物柜把东西拿出来。那我们怎么保证别人拿不走我们的东西,而且我们只能拿走我们存放的东西呢?这就涉及到KEY。

Glide缓存也不例外,他也会生成一个KEY
下面让我们通过源码来逐步分析

-> RequestBuilder.into 
	-> RequestManager.track
		-> RequestTrack.runRequest
			-> SingleRequest.begin
				-> SingleRequest.onSizeReady
					-> Engine.load
  public <R> LoadStatus load(...) {
    ...

    EngineKey key =
        keyFactory.buildKey(
            model,
            signature,
            width,
            height,
            transformations,
            resourceClass,
            transcodeClass,
            options);
   	EngineResource<?> memoryResource;
    synchronized (this) {
      memoryResource = loadFromMemory(key, isMemoryCacheable, startTime);
	....
  }

我们从into函数走到Engine.load函数,会看到Engin.load函数是生成我们缓存key的地方,会看到我们生成一个缓存key居然需要那么多参数,像宽高也是改变我们的key的生成。
缓存Key的生成条件我们看完了,那我们继续看内存缓存。

内存缓存
内存缓存也是从Engin.load函数获取看loadFromMenmory函数

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

    return null;
  }

可以看到上述代码,假如我们loadFromActiveResources获取活动缓存失败,则从loadFromCache获取LRU缓存,那这个LRU缓存如何来的呢?让我们继续看下去。

  Glie.with()
	-> Glide.getRetriever
		-> Glide.get
			-> Glide.checkAndInitializeGlide
				-> Glide.initializeGlide
					-> Glide.initializeGlide
						-> GlideBuilder.build
  @NonNull
  Glide build(@NonNull Context context) {
	...
    if (bitmapPool == null) {
      int size = memorySizeCalculator.getBitmapPoolSize();
      if (size > 0) {
        bitmapPool = new LruBitmapPool(size);
      } else {
        bitmapPool = new BitmapPoolAdapter();
      }
    }
	...

  }

当Glide初始化时,就会生成LruBitmapPool,Lru就是最近少使用算法(当内存不足时,把最近最少使用的一块缓存淘汰)
LruBitmapPool 遵循LRU算法。
总结:内存缓存获取:会先从活动缓存中获取,如果获取失败,则会从LRU缓存池中获取缓存。

RequestManager : 一个用于管理和启动Glide请求的类。可以使用活动、片段和连接生命周期事件智能地停止、启动和重新启动请求。通过实例化一个新对象进行检索,或者为了利用内置的“活动”和“片段”生命周期处理,请在“片段”或“活动”中使用静态Glide.load方法。

磁盘缓存

Glide.with(context)
     .load(url)
     .diskCacheStrategy(DiskCacheStrategy.NONE)
     .into(imageView);

把DiskCacheStrategy.NONE传入diskCacheStrategy方法,就可以把Glide的硬盘缓存功能禁用掉。
diskCacheStrategy可以接受这五个参数

DiskCacheStrategy.NONE:表示不缓存任何内容。
DiskCacheStrategy.DATA:表示只缓存原始图片。
DiskCacheStrategy.RESOURCE:表示只缓存转换过后的图片。
DiskCacheStrategy.ALL:表示既缓存原始图片,也缓存转换过后的图片。
DiskCacheStrategy.AUTOMATIC:表示让Glide根据图片资源智能地选择使用哪一种缓存策略(默认选项)
我们还是从Engin.load函数开始看

 public <R> LoadStatus load(...) {
  	...
    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;
  }

waitForExistingOrStartNewJob 主要做的事情是,会先从解析过的资源缓存获取,假如获取不到,就会从原始的资源磁盘缓存那里获取,假如都没有则会存放到磁盘缓存这里生成。

总结:Glide缓存获取顺序:内存缓存 ->磁盘缓存。

支持多种图片格式:

Glide支持的图片格式包括JPEG、PNG、GIF、WebP等常见图片格式。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值