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

BitmapFactory加载大尺寸资源图不显示,自定义图片加载遇问题求助

解决Android加载大尺寸图片不显示的问题

先帮你理清楚核心问题:你遇到的情况是因为系统对不同drawable文件夹下的图片会做密度缩放。默认的drawable文件夹属于mdpi密度等级,如果你的设备是xxhdpi(大部分主流手机都是),系统会把mdpi的图片放大3倍来适配屏幕——21001600的图放大后会变成63004800,这时候Bitmap的内存占用会飙升到近120MB(按ARGB_8888计算:630048004字节),虽然调试时能看到Bitmap对象存在,但GPU可能因为纹理尺寸超限或者内存不足,静默放弃渲染,所以看不到图片也没报错。移到drawable-xxhdpi后,系统不需要缩放(或缩放比例极小),内存占用回到正常的210016004≈13MB,自然能正常显示。

接下来针对两种场景给你解决方案:

一、加载资源文件夹内的大图片

除了放到对应密度文件夹,更稳妥的方式是主动对图片进行采样压缩,避免依赖系统的密度适配:

BitmapFactory.Options options = new BitmapFactory.Options();
// 先只获取图片尺寸,不加载到内存
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.drawable.imagename, options);

// 计算合适的采样率,比如目标宽高设为屏幕宽高(可根据你的需求调整)
int targetWidth = getResources().getDisplayMetrics().widthPixels;
int targetHeight = getResources().getDisplayMetrics().heightPixels;
int inSampleSize = calculateInSampleSize(options, targetWidth, targetHeight);

// 加载压缩后的图片
options.inJustDecodeBounds = false;
options.inSampleSize = inSampleSize;
// 可选:设置图片格式降低内存,比如RGB_565比ARGB_8888省一半内存
options.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.imagename, options);

这里的calculateInSampleSize方法可以这么写:

private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {
        final int halfHeight = height / 2;
        final int halfWidth = width / 2;
        // 找到最大的inSampleSize,使得采样后的宽高仍大于等于目标宽高
        while ((halfHeight / inSampleSize) >= reqHeight
               && (halfWidth / inSampleSize) >= reqWidth) {
            inSampleSize *= 2;
        }
    }
    return inSampleSize;
}

二、处理用户从相册选择的自定义图片

相册里的图片通常尺寸更大(比如手机拍照的4000*3000甚至更高),直接加载肯定会出问题,必须用采样压缩的方式处理,步骤如下:

  1. 从相册选择图片后,拿到图片的Uri,先获取图片的真实宽高:
// 假设你已经拿到了相册图片的Uri
Uri imageUri = ...;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;

// 通过Uri获取输入流来解码尺寸
try (InputStream is = getContentResolver().openInputStream(imageUri)) {
    BitmapFactory.decodeStream(is, null, options);
} catch (IOException e) {
    e.printStackTrace();
}
  1. 同样用上面的calculateInSampleSize计算采样率,然后加载压缩后的图片:
options.inJustDecodeBounds = false;
options.inSampleSize = calculateInSampleSize(options, targetWidth, targetHeight);
options.inPreferredConfig = Bitmap.Config.RGB_565;

try (InputStream is = getContentResolver().openInputStream(imageUri)) {
    Bitmap customBmp = BitmapFactory.decodeStream(is, null, options);
    // 把Bitmap设置到ImageView显示
    imageView.setImageBitmap(customBmp);
} catch (IOException e) {
    e.printStackTrace();
}

额外提醒:加载大图片后,记得在不需要显示的时候及时释放Bitmap资源(比如在Activity的onDestroy或者Fragment的onDestroyView中调用bmp.recycle(),并置为null),避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:44:51