我是靠谱客的博主 殷勤小懒猪,最近开发中收集的这篇文章主要介绍Glide 4.11 源码解析(二):缓存机制1.前言2. 缓存的入口3.弱引用缓存4. LruCache 缓存5. 硬盘缓存6. 总结,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

1.前言

在上一篇文章 Glide 4.11 源码解析(一):图片加载流程 中梳理出来图片的加载流程如下:

在 with 方法中通过 GlideBuilder 创建 RequestManagerRetriever 对象,并当做参数传入 Glide 的构造方法中。GlideBuilder 默认创建了网络加载线程池、磁盘缓存加载线程池、动画线程池、Bitmap池(用于复用)、数组池(用于复用)、内存缓存、磁盘缓存、图片加载引擎等。采用单例模式的方式获取到 Glide 对象,并通过 RequestManagerRetriever 对象获取 RequestManager 对象。RequestManager  创建了 RequestBuilder 对象,并将图片地址信息等赋值给 RequestBuilder 中的 model 变量。RequestManager  中的 TargetTracker 实现了 LifecycleListener 可以感应生命周期的变化。RequestBuilder  创建 了 SingleRequest  对象,SingleRequest  中创建了 Engine,在 Engine 中先检查是否存在活动资源缓存,以及内存缓存,如果没有缓存,则创建 EngineJob 来创建一个新的任务。在执行请求任务之前先检查磁盘缓存,如果不存在,则执行请求,默认的采用HttpURLConnection 为 Glide 底层完成网络请求的。最后通过回调将加载后的资源在 DrawableImageViewTarget  中将图片显示出来。

但是对于图片如何进行缓存以及图片如何从缓存中进行加载却一笔带过,此篇文章将详细梳理 Glide 的缓存是如何实现的。

2. 缓存的入口

Engine 的 load 方法:

  public <R> LoadStatus load(
      GlideContext glideContext,
      Object model,
      Key signature,
      int width,
      int height,
      Class<?> resourceClass,
      Class<R> transcodeClass,
      Priority priority,
      DiskCacheStrategy diskCacheStrategy,
      Map<Class<?>, Transformation<?>> transformations,
      boolean isTransformationRequired,
      boolean isScaleOnlyOrNoTransform,
      Options options,
      boolean isMemoryCacheable,
      boolean useUnlimitedSourceExecutorPool,
      boolean useAnimationPool,
      boolean onlyRetrieveFromCache,
      ResourceCallback cb,
      Executor callbackExecutor) {
    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);
    return null;
  }

在此方法中,首先通过传递进来的 model,ImageView 的 宽高等参数构建 EngineKey 类型的的对象 key,key 是图片的唯一标识。接着调用  memoryResource = loadFromMemory(key, isMemoryCacheable, startTime) 去或者 EngineResource 对象,EngineResource 就是图片资源。

loadFromMemory:

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

3.弱引用缓存

首先通过 isMemoryCacheable 判断是否支持内存缓存,如果为 false 则返回 null。接着调用 loadFromActiveResources 方法,并将代表唯一性的 key 传递进去:

  @Nullable
  private EngineResource<?> loadFromActiveResources(Key key) {
    EngineResource<?> active = activeResources.get(key);
    if (active != null) {
      active.acquire();
    }

    return active;
  }

从 activeResources 中获取 EngineResource。在 Engine 的构造方法中,如果参数传递 activeResources 为空,则创建一个新的 ActiveResources 类型的 activeResources 对象:

    if (activeResources == null) {
      activeResources = new ActiveResources(isActiveResourceRetentionAllowed);
    }
    this.activeResources = activeResources;
    activeResources.setListener(this);

ActiveResources :

  ActiveResources(boolean isActiveResourceRetentionAllowed) {
    this(
        isActiveResourceRetentionAllowed,
        java.util.concurrent.Executors.newSingleThreadExecutor(
            new ThreadFactory() {
              @Override
              public Thread newThread(@NonNull final Runnable r) {
                return new Thread(
                    new Runnable() {
                      @Override
                      public void run() {
                        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                        r.run();
                      }
                    },
                    "glide-active-resources");
              }
            }));
  }

  @VisibleForTesting
  ActiveResources(
      boolean isActiveResourceRetentionAllowed, Executor monitorClearedResourcesExecutor) {
    this.isActiveResourceRetentionAllowed = isActiveResourceRetentionAllowed;
    this.monitorClearedResourcesExecutor = monitorClearedResourcesExecutor;

    monitorClearedResourcesExecutor.execute(
        new Runnable() {
          @Override
          public void run() {
            cleanReferenceQueue();
          }
        });
  }

在构造方法中,开启线程调用 cleanReferenceQueue 去清除引用队列,用于初始化。再回调上面调用的 get(key) 方法:

  @Nullable
  synchronized EngineResource<?> get(Key key) {
    ResourceWeakReference activeRef = activeEngineResources.get(key);
    if (activeRef == null) {
      return null;
    }

    EngineResource<?> active = activeRef.get();
    if (active == null) {
      cleanupActiveReference(activeRef);
    }
    return active;
  }

调用 activeEngineResources 的 get(key) 方法获取 ResourceWeakReference 类型的 activeRef 。

 @VisibleForTesting final Map<Key, ResourceWeakReference> activeEngineResources = new HashMap<>();

activeEngineResources 是一个 HashMap,key 类型是前面传进来的代表图片唯一性的 key, value 类型是 ResourceWeakReference 类型。ResourceWeakReference 是 ActiveResources 的一个内部类:

  @VisibleForTesting
  static final class ResourceWeakReference extends WeakReference<EngineResource<?>> {
    @SuppressWarnings("WeakerAccess")
    @Synthetic
    final Key key;

    @SuppressWarnings("WeakerAccess")
    @Synthetic
    final boolean isCacheable;

    @Nullable
    @SuppressWarnings("WeakerAccess")
    @Synthetic
    Resource<?> resource;

    @Synthetic
    @SuppressWarnings("WeakerAccess")
    ResourceWeakReference(
        @NonNull Key key,
        @NonNull EngineResource<?> referent,
        @NonNull ReferenceQueue<? super EngineResource<?>> queue,
        boolean isActiveResourceRetentionAllowed) {
      super(referent, queue);
      this.key = Preconditions.checkNotNull(key);
      this.resource =
          referent.isMemoryCacheable() && isActiveResourceRetentionAllowed
              ? Preconditions.checkNotNull(referent.getResource())
              : null;
      isCacheable = referent.isMemoryCacheable();
    }

    void reset() {
      resource = null;
      clear();
    }
  }

可以看出 ResourceWeakReference 的父类是弱引用。当 activeEngineResources 获取到 ResourceWeakReference 类型的activeRef。如果 activeRef 不为空,则从 ResourceWeakReference 获取 EngineResource 类型的对象 active。如果 active 为空,则表示弱引用已经被回收,则调用 cleanupActiveReference(activeRef) 方法:

  @Synthetic
  void cleanupActiveReference(@NonNull ResourceWeakReference ref) {
    synchronized (this) {
      activeEngineResources.remove(ref.key);

      if (!ref.isCacheable || ref.resource == null) {
        return;
      }
    }

    EngineResource<?> newResource =
        new EngineResource<>(
            ref.resource, /*isMemoryCacheable=*/ true, /*isRecyclable=*/ false, ref.key, listener);
    listener.onResourceReleased(ref.key, newResource);
  }

当弱引用被回收后,则从 activeEngineResources 中移除。接着创建新的 EngineResource newResource ,并且调用 onResourceReleased(ref.key, newResource):

  @Override
  public void onResourceReleased(Key cacheKey, EngineResource<?> resource) {
    activeResources.deactivate(cacheKey);
    if (resource.isMemoryCacheable()) {
      cache.put(cacheKey, resource);
    } else {
      resourceRecycler.recycle(resource, /*forceNextFrame=*/ false);
    }
  }

在这里调用了 activeResources.deactivate(cacheKey) 方法:

  synchronized void deactivate(Key key) {
    ResourceWeakReference removed = activeEngineResources.remove(key);
    if (removed != null) {
      removed.reset();
    }
  }

再次从 activeEngineResources 中移除,确保弱引用已经被回收。如果支持内存缓存则将资源放入 MemoryCache 中,如果不支持,则进行资源的回收。

再次回到 loadFromActiveResources 方法:

  @Nullable
  private EngineResource<?> loadFromActiveResources(Key key) {
    EngineResource<?> active = activeResources.get(key);
    if (active != null) {
      active.acquire();
    }

    return active;
  }

当获取到 EngineResource,并且不为空,则调用 EngineResource 的 acquire() 方法:

  synchronized void acquire() {
    if (isRecycled) {
      throw new IllegalStateException("Cannot acquire a recycled resource");
    }
    ++acquired;
  }

在 EngineResource 中定义了一个变量 acquired,用于记录图片被引用的次数。调用 acquire() 方法,则变量加 1。当 acquired 变量大于 0,说明图片正在使用中。

小结

在 Engine 的 load 方法中,调用 loadFromMemory 方法去获取 EngineResource 对象,在此方法中首先判断是否支持缓存,如果不支持则返回 null,如果支持,则从 ActiveResources 中获取 EngineResource 对象。ActiveResources 的内部是一个 HashMap,而 HashMap 的值类型为 弱引用。如果弱引用已经被回收,则从 HashMap 中移除,并且创建一个新的 EngineResource 对象,并调用 onResourceReleased 方法,如果支持内存缓存则将资源放入 MemoryCache 中,如果不支持,则进行资源的回收。在 EngineResource 中定义了一个变量 acquired,用于记录图片被引用的次数。调用 acquire() 方法,则变量加 1。当 acquired 变量大于 0,说明图片正在使用中。

4. LruCache 缓存

在 loadFromMemory 方法中,先从弱引用(loadFromActiveResources(key)) 中获取 EngineResource,如果获取不到则调用 EngineResource<?> cached = loadFromCache(key) :

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

首先调用 getEngineResourceFromCache 方法获取 EngineResource:

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

cache 是 MemoryCache,而 MemoryCache 是一个 interface,那它的实现类是哪个呢?而 cache 是从 Engine 的构造方法中传入的。而 Engine 是在 GlideBuilder 的 build 方法中进行初始化的:

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

MemoryCache 的实现类是 LruResourceCache:

public class LruResourceCache extends LruCache<Key, Resource<?>> implements MemoryCache {
    ...
}

关于 LruCache 这里不再进行详述,可以参考我之前写过的文章:LruCache 源码解析。

当调用 getEngineResourceFromCache 方法获取到的 cache,这里的 cache 为 EngineResource 类型,当 cache 不为空,则调用 EngineResource 的 acquire() 方法,则变量 acquired 加 1。紧接着调用 activeResources.activate(key, cached) 方法:

  synchronized void activate(Key key, EngineResource<?> resource) {
    ResourceWeakReference toPut =
        new ResourceWeakReference(
            key, resource, resourceReferenceQueue, isActiveResourceRetentionAllowed);

    ResourceWeakReference removed = activeEngineResources.put(key, toPut);
    if (removed != null) {
      removed.reset();
    }
  }

这里创建弱引用,并且放入 HashMap 中。

小结:

在 loadFromMemory 方法中,如果从弱引用中获取 EngineResource,如果获取不到则调用 loadFromCache。此方法中从 LruResourceCache 中获取,LruResourceCache 继承于 LruCache。调用 LruResourceCache 的 remove 方法从 LruResourceCache 中获取EngineResource,如果获取到的 cache 不为空,则调用 EngineResource 的 acquire() 方法,则变量 acquired 加 1,引用加 1,并且将 EngineResource 放入弱引用的 HashMap 中。

5. 硬盘缓存

在 Engine 的 load 方法中,如果在弱引用的 HashMap 和 LruCache 中都获取不到资源,则调用 waitForExistingOrStartNewJob 方法:

  private <R> LoadStatus waitForExistingOrStartNewJob(
      GlideContext glideContext,
      Object model,
      Key signature,
      int width,
      int height,
      Class<?> resourceClass,
      Class<R> transcodeClass,
      Priority priority,
      DiskCacheStrategy diskCacheStrategy,
      Map<Class<?>, Transformation<?>> transformations,
      boolean isTransformationRequired,
      boolean isScaleOnlyOrNoTransform,
      Options options,
      boolean isMemoryCacheable,
      boolean useUnlimitedSourceExecutorPool,
      boolean useAnimationPool,
      boolean onlyRetrieveFromCache,
      ResourceCallback cb,
      Executor callbackExecutor,
      EngineKey key,
      long startTime) {
    ...

    EngineJob<R> engineJob =
        engineJobFactory.build(
            key,
            isMemoryCacheable,
            useUnlimitedSourceExecutorPool,
            useAnimationPool,
            onlyRetrieveFromCache);

    DecodeJob<R> decodeJob =
        decodeJobFactory.build(
            glideContext,
            model,
            key,
            signature,
            width,
            height,
            resourceClass,
            transcodeClass,
            priority,
            diskCacheStrategy,
            transformations,
            isTransformationRequired,
            isScaleOnlyOrNoTransform,
            onlyRetrieveFromCache,
            options,
            engineJob);

    jobs.put(key, engineJob);

    engineJob.addCallback(cb, callbackExecutor);
    engineJob.start(decodeJob);
    ...
  }

创建了 EngineJob 和 DecodeJob 并调用了 EngineJob 的 start(decodeJob) 方法:

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

采用线程池的方式启动了 DecodeJob,执行了 DecodeJob 的 run 方法:

  public void run() {
    ...
    DataFetcher<?> localFetcher = currentFetcher;
    try {
      if (isCancelled) {
        notifyFailed();
        return;
      }
      runWrapped();
    } catch (CallbackException e) {
       ...
    } catch (Throwable t) {
       ...
    } finally {
        ...
    }
  }

核心方法是 runWrapped 方法:

  private void runWrapped() {
    switch (runReason) {
      case INITIALIZE:
        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);
    }
  }

runReason 的值是 INITIALIZE,stage 返回 “RESOURCE_CACHE”,返回的 currentGenerator 对象为 ResourceCacheGenerator,并执行了 runGenerators() 方法:

  private void runGenerators() {
    currentThread = Thread.currentThread();
    startFetchTime = LogTime.getLogTime();
    boolean isStarted = false;
    while (!isCancelled
        && currentGenerator != null
        && !(isStarted = currentGenerator.startNext())) {
      stage = getNextStage(stage);
      currentGenerator = getNextGenerator();

      if (stage == Stage.SOURCE) {
        reschedule();
        return;
      }
    }
    ...
  }

通过 ResourceCacheGenerator 无法获取磁盘缓存,getNextGenerator() 得到的是 DataCacheGenerator,并执行了 startNext 方法:

  public boolean startNext() {
    while (modelLoaders == null || !hasNextModelLoader()) {
        ...
      Key originalKey = new DataCacheKey(sourceId, helper.getSignature());
      cacheFile = helper.getDiskCache().get(originalKey);
      if (cacheFile != null) {
        this.sourceKey = sourceId;
        modelLoaders = helper.getModelLoaders(cacheFile);
        modelLoaderIndex = 0;
      }
    }

    loadData = null;
    boolean started = false;
    while (!started && hasNextModelLoader()) {
      ModelLoader<File, ?> modelLoader = modelLoaders.get(modelLoaderIndex++);
      loadData =
          modelLoader.buildLoadData(
              cacheFile, helper.getWidth(), helper.getHeight(), helper.getOptions());
      if (loadData != null && helper.hasLoadPath(loadData.fetcher.getDataClass())) {
        started = true;
        loadData.fetcher.loadData(helper.getPriority(), this);
      }
    }
    return started;
  }

调用了 cacheFile = helper.getDiskCache().get(originalKey) 获取 cacheFile 对象,此处的 helper 是 DecodeHelper,getDiskCache() 方法:

  DiskCache getDiskCache() {
    return diskCacheProvider.getDiskCache();
  }

获取到的是 DiskCache,是从 diskCacheProvider 中获取,而 diskCacheProvider 的实现在 Engine 类中:

  private static class LazyDiskCacheProvider implements DecodeJob.DiskCacheProvider {

    private final DiskCache.Factory factory;
    private volatile DiskCache diskCache;

    LazyDiskCacheProvider(DiskCache.Factory factory) {
      this.factory = factory;
    }

    @VisibleForTesting
    synchronized void clearDiskCacheIfCreated() {
      if (diskCache == null) {
        return;
      }
      diskCache.clear();
    }

    @Override
    public DiskCache getDiskCache() {
      if (diskCache == null) {
        synchronized (this) {
          if (diskCache == null) {
            diskCache = factory.build();
          }
          if (diskCache == null) {
            diskCache = new DiskCacheAdapter();
          }
        }
      }
      return diskCache;
    }
  }

而 DiskCache 是从 DiskCache.Factory 中获取,DiskCache.Factory 的实现类是 DiskLruCacheFactory,通过调用 factory.build() 方法:

  public DiskCache build() {
    File cacheDir = cacheDirectoryGetter.getCacheDirectory();

    if (cacheDir == null) {
      return null;
    }

    if (!cacheDir.mkdirs() && (!cacheDir.exists() || !cacheDir.isDirectory())) {
      return null;
    }

    return DiskLruCacheWrapper.create(cacheDir, diskCacheSize);
  }
}

通过 DiskLruCacheWrapper 的 create 方法去创建 DiskLruCacheWrapper,而上面的 getDiskCache 的实现就是在此:

  private synchronized DiskLruCache getDiskCache() throws IOException {
    if (diskLruCache == null) {
      diskLruCache = DiskLruCache.open(directory, APP_VERSION, VALUE_COUNT, maxSize);
    }
    return diskLruCache;
  }

这里就是熟悉的 DiskLruCache ,关于 DiskLruCache 就不再继续往下追了。

当获取到 cacheFile 对象,cacheFile 的类型是 File,通过 cacheFile 去获取 ModelLoader 对象,ModelLoader 的实现类是 ByteBufferFileLoader,调用其中的内部类 ByteBufferFetcher 的 loadData 方法:

    @Override
    public void loadData(
        @NonNull Priority priority, @NonNull DataCallback<? super ByteBuffer> callback) {
      ByteBuffer result;
      try {
        result = ByteBufferUtil.fromFile(file);
      } catch (IOException e) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
          Log.d(TAG, "Failed to obtain ByteBuffer for file", e);
        }
        callback.onLoadFailed(e);
        return;
      }

      callback.onDataReady(result);
    }

这里最终调用回调 onDataReady,而 onDataReady 的实现类在 DataCacheGenerator 类中:

  @Override
  public void onDataReady(Object data) {
    cb.onDataFetcherReady(sourceKey, data, loadData.fetcher, DataSource.DATA_DISK_CACHE, sourceKey);
  }

又一个回调,回调 onDataFetcherReady 的实现类在 DecodeJob 中:

  @Override
  public void onDataFetcherReady(
      Key sourceKey, Object data, DataFetcher<?> fetcher, DataSource dataSource, Key attemptedKey) {
    ...

    if (Thread.currentThread() != currentThread) {
      runReason = RunReason.DECODE_DATA;
      callback.reschedule(this);
    } else {
      GlideTrace.beginSection("DecodeJob.decodeFromRetrievedData");
      try {
        decodeFromRetrievedData();
      } finally {
        GlideTrace.endSection();
      }
    }
  }

调用了 decodeFromRetrievedData 方法:

  private void decodeFromRetrievedData() {
    ...
    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);
    } else {
      runGenerators();
    }
  }

返回一个 Resource,Resource 不为空,则调用 notifyEncodeAndRelease 方法:

  private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {
    ...

    notifyComplete(result, dataSource);

    ...
  }
  private void notifyComplete(Resource<R> resource, DataSource dataSource) {
    setNotifiedOrThrow();
    callback.onResourceReady(resource, dataSource);
  }

接下来的步骤在文章: Glide 4.11 源码解析(一):图片加载流程 中已经分析,就不再详述了。

小结:

如果在弱引用的 HashMap 和 LruCache 中都获取不到资源,则创建 EngineJob 启动线程池并启动线程 EngineJob 并运行对应的 run 方法。接着调用了 DataCacheGenerator 的 startNext 方法。 startNext 方法中调用 DecodeHelper 的 getDiskCache ,而 getDiskCache 是在 DiskLruCacheFactory 中通过 DiskLruCacheWrapper create 方法获取到的 DiskLruCache。

6. 总结

在获取图片的流程中,调用 Engine 的 load 方法,调用 loadFromMemory 方法去获取 EngineResource 对象,在此方法中首先判断是否支持缓存,如果不支持则返回 null,如果支持,则从 ActiveResources 中获取 EngineResource 对象。ActiveResources 的内部是一个 HashMap,而 HashMap 的值类型为 弱引用。如果弱引用已经被回收,则从 HashMap 中移除,并且创建一个新的 EngineResource 对象,并调用 onResourceReleased 方法,如果支持内存缓存则将资源放入 MemoryCache 中,如果不支持,则进行资源的回收。在 EngineResource 中定义了一个变量 acquired,用于记录图片被引用的次数。调用 acquire() 方法,则变量加 1。当 acquired 变量大于 0,说明图片正在使用中。

在 loadFromMemory 方法中,如果从弱引用中获取 EngineResource,如果获取不到则调用 loadFromCache。此方法中从 LruResourceCache 中获取,LruResourceCache 继承于 LruCache。调用 LruResourceCache 的 remove 方法从 LruResourceCache 中获取EngineResource,如果获取到的 cache 不为空,则调用 EngineResource 的 acquire() 方法,则变量 acquired 加 1,引用加 1,并且将 EngineResource 放入弱引用的 HashMap 中。

如果在弱引用的 HashMap 和 LruCache 中都获取不到资源,则创建 EngineJob 启动线程池并启动线程 EngineJob 并运行对应的 run 方法。接着调用了 DataCacheGenerator 的 startNext 方法。 startNext 方法中调用 DecodeHelper 的 getDiskCache ,而 getDiskCache 是在 DiskLruCacheFactory 中通过 DiskLruCacheWrapper create 方法获取到的 DiskLruCache。

最后

以上就是殷勤小懒猪为你收集整理的Glide 4.11 源码解析(二):缓存机制1.前言2. 缓存的入口3.弱引用缓存4. LruCache 缓存5. 硬盘缓存6. 总结的全部内容,希望文章能够帮你解决Glide 4.11 源码解析(二):缓存机制1.前言2. 缓存的入口3.弱引用缓存4. LruCache 缓存5. 硬盘缓存6. 总结所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(33)

评论列表共有 0 条评论

立即
投稿
返回
顶部