glide_ModelLoaderKey__0">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.InputStreamclass 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))}//这里使用了AudioCoverSignaturereturn 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.MessageDigestclass 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.InputStreamclass 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}//这里使用ObjectKeyreturn ModelLoader.LoadData(ObjectKey(path), AudioCoverFetcher(model))}override fun handles(model: AudioMediaData) = true
}
问题解决了