Glide 转换内存泄漏

Glide Transformation memory leak

我在使用 Glide 时遇到内存泄漏问题。这是 LeakCanary 的追踪。

 D/LeakCanary: ├─ android.provider.FontsContract
 D/LeakCanary: │    Leaking: NO (HomeApplication↓ is not leaking and a class is never leaking)
 D/LeakCanary: │    GC Root: System class
 D/LeakCanary: │    ↓ static FontsContract.sContext
 D/LeakCanary: ├─  <package>.HomeApplication
 D/LeakCanary: │    Leaking: NO (Application is a singleton)
 D/LeakCanary: │    HomeApplication does not wrap an activity context
 D/LeakCanary: │    ↓ HomeApplication.mComponentCallbacks
 D/LeakCanary: │                      ~~~~~~~~~~~~~~~~~~~
 D/LeakCanary: ├─ java.util.ArrayList
 D/LeakCanary: │    Leaking: UNKNOWN
 D/LeakCanary: │    ↓ ArrayList.elementData
 D/LeakCanary: │                ~~~~~~~~~~~
 D/LeakCanary: ├─ java.lang.Object[]
 D/LeakCanary: │    Leaking: UNKNOWN
 D/LeakCanary: │    ↓ array Object[].[1]
 D/LeakCanary: │                     ~~~
 D/LeakCanary: ├─ com.bumptech.glide.Glide
 D/LeakCanary: │    Leaking: UNKNOWN
 D/LeakCanary: │    ↓ Glide.memoryCache
 D/LeakCanary: │            ~~~~~~~~~~~
 D/LeakCanary: ├─ com.bumptech.glide.load.engine.cache.LruResourceCache
 D/LeakCanary: │    Leaking: UNKNOWN
 D/LeakCanary: │    ↓ LruResourceCache.cache
 D/LeakCanary: │                       ~~~~~
 D/LeakCanary: ├─ java.util.LinkedHashMap
 D/LeakCanary: │    Leaking: UNKNOWN
 D/LeakCanary: │    ↓ LinkedHashMap.tail
 D/LeakCanary: │                    ~~~~
 D/LeakCanary: ├─ java.util.LinkedHashMap$LinkedHashMapEntry
 D/LeakCanary: │    Leaking: UNKNOWN
 D/LeakCanary: │    ↓ LinkedHashMap$LinkedHashMapEntry.key
 D/LeakCanary: │                                       ~~~
 D/LeakCanary: ├─ com.bumptech.glide.load.engine.EngineKey
 D/LeakCanary: │    Leaking: UNKNOWN
 D/LeakCanary: │    ↓ EngineKey.transformations
 D/LeakCanary: │                ~~~~~~~~~~~~~~~
 D/LeakCanary: ├─ com.bumptech.glide.util.CachedHashCodeArrayMap
 D/LeakCanary: │    Leaking: UNKNOWN
 D/LeakCanary: │    ↓ CachedHashCodeArrayMap.mArray
 D/LeakCanary: │                             ~~~~~~
 D/LeakCanary: ├─ java.lang.Object[]
 D/LeakCanary: │    Leaking: UNKNOWN
 D/LeakCanary: │    ↓ array Object[].[1]
 D/LeakCanary: │                     ~~~
 D/LeakCanary: ├─ <package>.<some class>
 D/LeakCanary: │    Leaking: UNKNOWN
 D/LeakCanary: │    Anonymous class implementing com.bumptech.glide.load.Transformation
 D/LeakCanary: │    ↓ <some class>.this[=10=]
 D/LeakCanary: │                ~~~~~~
 D/LeakCanary: ├─ <package>.<some class>
 D/LeakCanary: │    Leaking: UNKNOWN
 D/LeakCanary: │    ↓ <some class>.activity
 D/LeakCanary: │              ~~~~~~~~
 D/LeakCanary: ╰→ <package>.<some activity>
 D/LeakCanary: ​     Leaking: YES (Activity#mDestroyed is true and ObjectWatcher was watching this)
 D/LeakCanary: ​     key = 632286af-8d9e-4b05-bc8f-5974ca16931b
 D/LeakCanary: ​     watchDurationMillis = 2957886
 D/LeakCanary: ​     retainedDurationMillis = 2952885

所以这就是说转换由 glide 缓存并且转换引用 activity。 我的印象是 Glide 是生命周期感知的,但是是的,我知道它可能只适用于加载请求。 所以我在考虑可能的解决方案:

  1. 不要在转换代码中引用 activity
  2. 清除滑行的状态,以便清除缓存中的转换。
  3. 要求 glide 不缓存转换。

从这里到哪里去?

此外,我现在是否缺少完全错误的东西。这是转换代码:

new Transformation<Drawable>() {
      @NonNull
      @Override
      public Resource<Drawable> transform(
          @NonNull Context context,
          @NonNull Resource<Drawable> resource,
          int outWidth,
          int outHeight) {
        Drawable albumArt = resource.get();
        int backgroundColor;
        if (albumArt instanceof BitmapDrawable) {
          backgroundColor =
              <some util class>.getBackgroundColorForBitmap(
                  ((BitmapDrawable) albumArt).getBitmap());

        } else {
          backgroundColor = defaultBackgroundScrimColor;
        }
        Drawable[] layers = {
          albumArt, <some util class>.getGradientOverlay(backgroundColor)
        };
        return new SimpleResource<>(new LayerDrawable(layers));
      }

      @Override
      public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {}
    };
  }

此外,我仍在尝试找出如何在转换代码中引用 activity。

我最终没有使用 Glide 转换,而是在从 glide 中获取 onCustomTarget 后手动转换 drawable。