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
}

问题解决了

相关推荐
老码沉思录2 小时前
Android开发实战班 -应用架构 - MVVM 架构模式
android·架构
zhoujun7985 小时前
B站直播模块解读——MVVM类似物
android
L72566 小时前
Android12 Wifi的连接过程梳理
android·wifi
郝晨妤6 小时前
鸿蒙原生应用开发元服务 元服务是什么?和App的关系?(保姆级步骤)
android·ios·华为od·华为·华为云·harmonyos·鸿蒙
枫__________7 小时前
kotlin 协程 job的cancel与cancelAndJoin区别
android·开发语言·kotlin
sinat_384241098 小时前
修改Android Studio项目配置JDK路径和项目Gradle路径的GUI工具
android·java·android studio
bingbingyihao8 小时前
代码辅助工具 GPT / Cursor
android·java·gpt
少说多做3438 小时前
Android 使用 LiveData/OnCheckedChangeListener 来监听变量变化
android·java·android-studio
麻花疼不疼8 小时前
php 使用mqtt
android·开发语言·php
@解忧杂货铺9 小时前
Android和IOS的区别
android·ios·cocoa