glide ModelLoader的Key错误使用 可能造成的内存泄漏

glide ModelLoader的Key错误使用 可能造成的内存泄漏

业务场景

之前项目性能优化,在自定义的AppGlideModule中的registerComponents方法append了自定义ModelLoaderFactory,然后有很多个File对象出现了内存泄漏,后面定位到以下场景,代码如下:

kotlin 复制代码
import com.bumptech.glide.load.Options
import com.bumptech.glide.load.model.ModelLoader
import com.bumptech.glide.signature.ObjectKey
import com.fawvw.hmi.media.mediacommon.model.mediadata.AudioMediaData
import java.io.InputStream

class AudioModuleLoader : ModelLoader<AudioMediaData, InputStream> {
    override fun buildLoadData(
        model: AudioMediaData,
        width: Int,
        height: Int,
        options: Options
    ): ModelLoader.LoadData<InputStream> {
        val path = if (model.albumArt != null) {
            "${model.artist}${model.duration}${model.album}"
        } else {
            model.uri
        }
        return ModelLoader.LoadData(ObjectKey(path), AudioCoverFetcher(model))
    }
	//这里使用了AudioCoverSignature
	 return ModelLoader.LoadData(AudioCoverSignature(path), AudioCoverFetcher(model))
    }

    override fun handles(model: AudioMediaData) = true
}
kotlin 复制代码
import com.bumptech.glide.load.Key
import java.io.File
import java.security.MessageDigest

class AudioCoverSignature(private val path:String): Key {
    private val stringBuilder by lazy {
        StringBuilder()
    }
	//这个file内存泄漏了
    private val file by lazy {
        File(path)
    }
    override fun updateDiskCacheKey(messageDigest: MessageDigest) {
        stringBuilder.append(file.lastModified()).append(file.absolutePath)
        val bs = stringBuilder.toString().encodeToByteArray()
        messageDigest.update(bs, 0, bs.size)
    }
}

泄露的原因是因为,AudioCoverSignature类只重写了updateDiskCacheKey方法,没有重写equals方法,而ModelLoader.LoadData方法的入参key是用来找缓存的,每一个都找不到,导致内存泄漏

kotlin 复制代码
  /**
   * Contains a set of {@link com.bumptech.glide.load.Key Keys} identifying the source of the load,
   * alternate cache keys pointing to equivalent data, and a {@link
   * com.bumptech.glide.load.data.DataFetcher} that can be used to fetch data not found in cache.
   *
   * @param <Data> The type of data that well be loaded.
   */
  class LoadData<Data> {
    public final Key sourceKey;
    public final List<Key> alternateKeys;
    public final DataFetcher<Data> fetcher;
	...

解决方法

将自定义AudioCoverSignature删除,使用ObjectKey解决此问题

kotlin 复制代码
import com.bumptech.glide.load.Options
import com.bumptech.glide.load.model.ModelLoader
import com.bumptech.glide.signature.ObjectKey
import com.fawvw.hmi.media.mediacommon.model.mediadata.AudioMediaData
import java.io.InputStream

class AudioModuleLoader : ModelLoader<AudioMediaData, InputStream> {
    override fun buildLoadData(
        model: AudioMediaData,
        width: Int,
        height: Int,
        options: Options
    ): ModelLoader.LoadData<InputStream> {
        val path = if (model.albumArt != null) {
            "${model.artist}${model.duration}${model.album}"
        } else {
            model.uri
        }
		//这里使用ObjectKey
        return ModelLoader.LoadData(ObjectKey(path), AudioCoverFetcher(model))
    }

    override fun handles(model: AudioMediaData) = true
}

问题解决了

相关推荐
张可37 分钟前
历时两年半开发,Fread 项目现在决定开源,基于 Kotlin Multiplatform 和 Compose Multiplatform 实现
android·前端·kotlin
余辉zmh1 小时前
【Linux系统篇】:信号的生命周期---从触发到保存与捕捉的底层逻辑
android·java·linux
孤鸿玉2 小时前
[Flutter小试牛刀] 低配版signals,添加多层监听链
android·前端·响应式设计
雨和卡布奇诺2 小时前
LiveData源码浅析
android
淡蓝色_justin2 小时前
Hilt-plus 简介
android·android jetpack
app1e2342 小时前
ctfshow web入门 命令执行(29-77)
android·前端
xiangxiongfly9153 小时前
Kotlin 边界限制
kotlin·coercein
恋猫de小郭4 小时前
Flutter 在 Dart 3.8 开始支持 Null-Aware Elements 语法,自动识别集合里的空元素
android·前端·flutter
fatiaozhang95275 小时前
咪咕MG101_晨星MSO9380芯片_安卓5.1.1_免拆卡刷固件包
android·电视盒子·av1·机顶盒rom·魔百盒刷机