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
}

问题解决了

相关推荐
婵鸣空啼3 小时前
GD图像处理与SESSiON
android
sunly_3 小时前
Flutter:导航固定背景图,滚动时导航颜色渐变
android·javascript·flutter
用户2018792831674 小时前
简单了解android.permission.MEDIA_CONTENT_CONTROL权限
android
_一条咸鱼_4 小时前
Android Runtime类卸载条件与资源回收策略(29)
android·面试·android jetpack
顾林海4 小时前
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
android·面试·性能优化
砖厂小工4 小时前
Now In Android 精讲 8 - Gradle build-logic 现代构建逻辑组织方式
android
玲小珑4 小时前
Auto.js 入门指南(八)高级控件与 UI 自动化
android·前端
harry235day5 小时前
Compose 带动画的待办清单列表页
android·android jetpack
vocal5 小时前
我的安卓第一课:四大组件之一Activity及其组件RecyclerView
android
咕噜企业签名分发-淼淼5 小时前
如何实现安卓端与苹果端互通的多种方案
android