You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Glide+RecyclerView加载图片,300张后出现内存溢出问题求助

嘿,我来帮你搞定这个内存溢出的问题!虽然单张图片只有4KB,但你得知道:图片在内存中的占用是按像素计算的,不是原文件大小——哪怕原文件很小,加载成Bitmap后可能会占用好几倍甚至几十倍的内存,300张叠加起来就很容易爆内存了。结合你的代码和场景,我给你几个针对性的优化方案:

1. 强制Glide按ImageView实际尺寸加载图片

GridLayout里的ImageView尺寸是固定的,但Glide可能没有正确识别控件的实际大小,导致加载了远超需求的Bitmap。你可以直接指定加载的尺寸,让Glide只生成适合控件的Bitmap:

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    // 先清除复用View上的旧请求,避免资源浪费
    Glide.with(mMainActivity).clear(holder.posterPath);
    
    MovieItem item = mList.get(position);
    Glide.with(mMainActivity)
         .load(item.getPosterPath())
         .thumbnail(0.5f)
         // 直接指定ImageView的实际宽高,或者写死固定的像素值(比如你的Grid item是100x150)
         .override(holder.posterPath.getWidth(), holder.posterPath.getHeight())
         .centerCrop() // 或者fitCenter,根据你的布局需求选择
         .into(holder.posterPath);
}

如果你的Grid item尺寸是固定的(比如xml里用dp指定了宽高),直接写死像素值会更稳妥,比如override(120, 180)(换成你的实际尺寸)。

2. 自定义Glide内存缓存配置

默认的LRU缓存可能不够适配你的场景,你可以手动调整缓存大小,同时开启Bitmap复用减少内存碎片:
先创建一个GlideModule类:

@GlideModule
public class CustomGlideModule extends AppGlideModule {
    @Override
    public void applyOptions(Context context, GlideBuilder builder) {
        // 设置内存缓存大小,比如取设备可用内存的1/8,或者直接设20MB(根据设备调整)
        int memoryCacheSize = 1024 * 1024 * 20; 
        builder.setMemoryCache(new LruResourceCache(memoryCacheSize));
        
        // 开启Bitmap复用池,减少内存分配和碎片
        builder.setBitmapPool(new LruBitmapPool(memoryCacheSize));
    }
}

然后在AndroidManifest.xml里添加这个Module的配置:

<meta-data
    android:name="com.yourpackage.CustomGlideModule"
    android:value="GlideModule" />
3. 优化RecyclerView的复用逻辑

一定要在绑定新数据前清除旧的Glide请求,避免复用的ImageView加载旧图片,同时释放不必要的资源:

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    // 关键:清除之前的加载请求,防止内存泄漏和旧图片残留
    Glide.with(mMainActivity).clear(holder.posterPath);
    
    // 然后加载新图片
    MovieItem item = mList.get(position);
    Glide.with(mMainActivity)
         .load(item.getPosterPath())
         .thumbnail(0.5f)
         .override(holder.posterPath.getWidth(), holder.posterPath.getHeight())
         .into(holder.posterPath);
}

另外,别在Adapter外部持有ViewHolder的强引用,避免内存泄漏。

4. 调整Bitmap解码格式减少内存占用

如果你的图片不需要透明通道,可以把解码格式换成RGB_565,这样每个像素的内存占用从4字节降到2字节,直接减少一半内存:

Glide.with(mMainActivity)
     .load(item.getPosterPath())
     .thumbnail(0.5f)
     .format(DecodeFormat.PREFER_RGB_565)
     .override(holder.posterPath.getWidth(), holder.posterPath.getHeight())
     .into(holder.posterPath);
5. 按需调整缓存策略

如果这些图片不需要快速复用,可以跳过内存缓存,只缓存到磁盘,进一步减少内存占用:

Glide.with(mMainActivity)
     .load(item.getPosterPath())
     .thumbnail(0.5f)
     .skipMemoryCache(true) // 跳过内存缓存
     .diskCacheStrategy(DiskCacheStrategy.RESULT) // 只缓存处理后的图片,节省磁盘空间
     .into(holder.posterPath);

不过这个要根据业务需求来,如果需要快速滑动加载,还是保留内存缓存更合适。

最后,你可以用Android Profiler的Memory面板查看内存占用详情,确认是不是Bitmap占用了大部分内存,也可以排查有没有其他内存泄漏的情况(比如Activity的引用被意外持有)。

内容的提问来源于stack exchange,提问作者Overflow 404

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:53:44