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 是生命周期感知的,但是是的,我知道它可能只适用于加载请求。
所以我在考虑可能的解决方案:
- 不要在转换代码中引用 activity
- 清除滑行的状态,以便清除缓存中的转换。
- 要求 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。
我在使用 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 是生命周期感知的,但是是的,我知道它可能只适用于加载请求。 所以我在考虑可能的解决方案:
- 不要在转换代码中引用 activity
- 清除滑行的状态,以便清除缓存中的转换。
- 要求 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。