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

ImageView设置图片触发OutOfMemoryError问题求解

解决ImageView设置大图片触发OutOfMemoryError的问题

这个问题很典型——你遇到的OutOfMemoryError是因为要加载的图片太大了,从错误日志里能看到系统尝试分配715MB的内存,这显然远远超过了App能获取的内存上限。直接用setImageResource()会把整张图片解码后加载到内存,哪怕你的ImageView尺寸很小,也会加载原图的全部像素,最终导致内存溢出。

先排查核心原因

先确认R.drawable.aresbkg这张JPG的实际尺寸:按错误里的内存计算,715MB对应约1.86亿像素(每个ARGB_8888格式像素占4字节),差不多是13600×13600的超大图,这种尺寸完全不适合直接在Android应用里加载。之前其他应用没出现问题,大概率是那些应用用的图片尺寸都在合理范围内。

解决方案推荐

下面按从手动到自动的顺序,给你几种可行的解决方法:

1. 手动压缩加载图片(自定义逻辑)

通过BitmapFactory.Options来采样压缩,只加载和ImageView尺寸匹配的像素:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    button = findViewById(R.id.button);
    immagine = findViewById(R.id.imageView2);

    // 获取ImageView的实际显示尺寸(onCreate中直接获取可能为0,用post延迟获取)
    immagine.post(() -> {
        int targetWidth = immagine.getWidth();
        int targetHeight = immagine.getHeight();

        // 第一步:只获取图片原始尺寸,不加载到内存
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(getResources(), R.drawable.aresbkg, options);
        int originalWidth = options.outWidth;
        int originalHeight = options.outHeight;

        // 计算采样率:找到最大的2的倍数,让采样后的尺寸不超过目标尺寸
        int inSampleSize = 1;
        if (originalHeight > targetHeight || originalWidth > targetWidth) {
            final int halfHeight = originalHeight / 2;
            final int halfWidth = originalWidth / 2;
            while ((halfHeight / inSampleSize) >= targetHeight
                    && (halfWidth / inSampleSize) >= targetWidth) {
                inSampleSize *= 2;
            }
        }

        // 第二步:加载压缩后的图片
        options.inJustDecodeBounds = false;
        options.inSampleSize = inSampleSize;
        options.inPreferredConfig = Bitmap.Config.RGB_565; // 无透明需求时用,省一半内存
        Bitmap compressedBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.aresbkg, options);
        immagine.setImageBitmap(compressedBitmap);
    });
}
  • 关键点:inJustDecodeBounds=true时不会加载Bitmap,只是读取尺寸;inSampleSize是采样比例,设为2就是宽高各缩为1/2,内存占用是原图的1/4;RGB_565格式比默认的ARGB_8888省一半内存(适合无透明通道的图片)。

2. 使用图片加载库(更省心的方案)

用Glide、Picasso这类成熟的图片加载库,它们会自动处理图片压缩、内存缓存、磁盘缓存,完全不用自己写复杂逻辑:
比如用Glide(需要先在build.gradle里添加依赖):

// 先添加依赖:implementation 'com.github.bumptech.glide:glide:4.16.0'
// 然后在代码里一行搞定
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    button = findViewById(R.id.button);
    immagine = findViewById(R.id.imageView2);

    Glide.with(this).load(R.drawable.aresbkg).into(immagine);
}

Glide会自动根据ImageView的尺寸压缩图片,还会智能管理内存,避免OOM,这是大多数Android开发者的首选方案。

3. 其他优化细节

  • 把图片放在正确的drawable目录:比如高分辨率图片放在drawable-xxhdpi,不要放在默认的drawable(会被系统按mdpi缩放,导致内存占用变大)。
  • 手动回收Bitmap(如果是自己加载的):在Activity销毁时回收内存,避免泄漏:
@Override
protected void onDestroy() {
    super.onDestroy();
    Drawable drawable = immagine.getDrawable();
    if (drawable instanceof BitmapDrawable) {
        Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
        if (bitmap != null && !bitmap.isRecycled()) {
            bitmap.recycle();
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 09:07:26