如何在Android中加载大图像并避免内存不足错误?

2024-04-21

我正在开发一个使用大图像的应用程序(1390 × 870:150kb - 50kb)。我在点击触发器/ImageView 时添加图像。

在某个时刻我遇到内存不足错误:

java.lang.OutOfMemoryError
E/AndroidRuntime(23369): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
E/AndroidRuntime(23369): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:613)
E/AndroidRuntime(23369): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:378)

要调整图像大小,我正在这样做:

Bitmap productIndex = null;
final String imageLoc = IMAGE_LOCATION;
InputStream imageStream;
try {
     imageStream = new FileInputStream(imageLoc);
     productIndex = decodeSampledBitmapFromResource(getResources(), imageLoc, 400, 400);

     productIV.setImageBitmap(productIndex);
     } catch (FileNotFoundException e1) {
          // TODO Auto-generated catch block
          e1.printStackTrace();
     }
}


public static Bitmap decodeSampledBitmapFromResource(Resources res, String resId, int reqWidth, int reqHeight) {

// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(resId, options);

// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(resId, options);
}

public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;

if (height > reqHeight || width > reqWidth) {

    final int halfHeight = height / 3;
    final int halfWidth = width / 3;

    // Calculate the largest inSampleSize value that is a power of 2 and keeps both
    // height and width larger than the requested height and width.
    while ((halfHeight / inSampleSize) > reqHeight
            && (halfWidth / inSampleSize) > reqWidth) {
        inSampleSize *= 2;
    }
}

return inSampleSize;
}

我从 Android 文档中得到了这种调整大小以节省空间的方法:高效加载大位图 http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

根据日志,这就像是罪魁祸首decodeSampledBitmapFromResource方法 :

return BitmapFactory.decodeFile(resId, options);

- - - 编辑 - - - 以下是我将每个项目添加到 FrameLayout 的方法。

for(int ps=0;ps<productSplit.size();ps++){
    //split each product by the equals sign
    List<String> productItem = Arrays.asList(productSplit.get(ps).split("="));

    String tempCarID = productItem.get(0);
    tempCarID = tempCarID.replace(" ", "");
    if(String.valueOf(carID).equals(tempCarID)){

        ImageView productIV = new ImageView(Configurator.this);
        LayoutParams productParams = new LayoutParams(
                LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        productIV.setId(Integer.parseInt(partIdsList.get(x)));
        productIV.setLayoutParams(productParams);

        final String imageLoc = productItem.get(2);

        InputStream imageStream;
        try {
            imageStream = new FileInputStream(imageLoc);
            productIndex = decodeSampledBitmapFromResource(getResources(), imageLoc, 400, 400);
            productIV.setImageBitmap(productIndex);
        } catch (FileNotFoundException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        productLayers.addView(productIV);

    }
}

您可以使用另一个位图配置来大幅减小图像的大小。默认值为 RGB 配置 ARGB8888,这意味着使用四个 8 位通道(红、绿、蓝、alhpa)。 Alpha 是位图的透明度。这会占用大量内存 - 图像大小 X 4。因此,如果图像大小为 4 兆像素,则 16 兆字节将立即分配在堆上 - 很快就会耗尽内存。

相反 - 使用 RGB_565 这在一定程度上会降低质量 - 但为了补偿这一点,您可以抖动图像。

因此,在您的方法中添加以下片段:decodeSampledBitmapFromResource:

 options.inPreferredConfig = Config.RGB_565;
 options.inDither = true;

在你的代码中:

 public static Bitmap decodeSampledBitmapFromResource(Resources res, String resId, int    reqWidth, int reqHeight) {

 // First decode with inJustDecodeBounds=true to check dimensions
 final BitmapFactory.Options options = new BitmapFactory.Options();
 options.inJustDecodeBounds = true;
 BitmapFactory.decodeFile(resId, options);

 // Calculate inSampleSize
 options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

 // Decode bitmap with inSampleSize set
 options.inJustDecodeBounds = false;
 options.inPreferredConfig = Config.RGB_565;
 options.inDither = true;
 return BitmapFactory.decodeFile(resId, options);
 }

参考:

http://developer.android.com/reference/android/graphics/Bitmap.Config.html#ARGB_8888 http://developer.android.com/reference/android/graphics/Bitmap.Config.html#ARGB_8888

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在Android中加载大图像并避免内存不足错误? 的相关文章

随机推荐

  • NET Remoting 和 MarshalByRefObject 真的死了吗?

    我正在开发一个需要应用程序域内进程间和进程间机器内通信的项目 是的 我知道 NET Remoting 被广泛认为是一种遗留技术 但我面临着两个非常特殊的问题 也许在这些情况下 WCF 并不能完全替代 NET Remoting 1 AppDo
  • XSLT 增强 Hadoop 配置

    什么是可以根据名称添加或替换属性值的 XSLT 版本 1 0 转换 例如 给定以下输入 XML
  • 如何管理共享库中的 spring-cloud bootstrap 属性?

    我正在构建一个库 该库为使用我们的应用程序提供固执己见的配置Spring Cloud Config Eureka设置 这个想法是将此配置作为自定义启动器提供 在各个微服务应用程序中很少或没有与 Spring Cloud 相关的样板 此时 我
  • 续集,关联返回时出现问题

    我目前正在尝试 Sequelize 并有两个对象 一个Person and Position 当获取人员列表时我想得到他们的位置 models var User sequelize define user first name Sequel
  • 为什么 ["A","B","C"].map(String.prototype.toLowerCase.call) 不起作用? [复制]

    这个问题在这里已经有答案了 当然 这会返回您所期望的结果 A B C map function x return x toLowerCase gt a b c 使用 String prototype toLowerCase call 也是如
  • 我如何查看我的应用程序使用了多少超出其虚拟机预算的内存?

    我查看了 DDMS 但没有看到任何内容 谢谢 您应该在 DDMS 的 设备 视图中单击 更新堆 按钮
  • 压缩独特的数据流

    我有大量的整数数组 每个整数都有几千个整数 每个整数通常与前一个整数相同或仅相差一两位 我想将每个阵列缩小到尽可能小 以减少磁盘 IO Zlib 将其缩小到原始大小的 25 左右 这很好 但我不认为它的算法特别适合这个问题 有谁知道对于此类
  • 导航栏中的复选框小部件闪亮

    是否可以在导航栏行中创建复选框小部件 这是一example http www bootply com 103995 我的想法 下面创建一个checkboxInput 但交互性似乎无法正常工作 library shiny ui lt navb
  • 类中的int是存储在栈上还是堆上? [复制]

    这个问题在这里已经有答案了 可能的重复 栈和堆理解问题 https stackoverflow com questions 2559271 stack heap understanding question 有人告诉我使用 var 真的很慢
  • 如何将可观察的响应投射到本地对象

    在当前的 Angular 6 应用程序中 有一个订阅 observable 来自 RESTful 服务的响应 this activatedRoute data subscribe bag gt console log bag this ba
  • Android发送大量短信

    我有一个应用程序 它会向中央服务器发送大量短信 每个用户每天可能会发送约 300 个文本 SMS 消息被用作网络层 因为 SMS 几乎无处不在 而移动互联网却不然 该应用程序旨在供许多移动互联网尚未普及的第三世界国家使用 当我达到 100
  • 最大限度地降低重新分配人员的成本

    我有属于不同类别的个人 他们位于不同的地方 区 这些人口预计将从population值低于 到demand value population and demand by category and zone lt tibble tribble
  • jQuery 选择更改显示/隐藏 div 事件

    我正在尝试创建一个表单 当选择选择元素 parcel 时 它将显示一个 div 但当未选择它时 我想隐藏该 div 这是我目前的标记 到目前为止 这是我的 HTML div class row Type div
  • 从 AOSP 编译电子邮件应用程序

    我想向 AOSP 电子邮件应用程序添加一些不再受支持的功能 所以我克隆了存储库here https github com android platform packages apps email 这是一个 Eclipse 项目 并将其迁移到
  • C++:防止多个函数同时执行

    我问这个问题是因为mutex我发现文档处理单个函数 我认为我的情况很常见 我的问题是以下代码是否不仅会阻止func1 OR func2 并行执行多次 但它是否也会阻止func1 AND func2 同时执行 include
  • 在 UITableView 标头中包含的 UIImageView 上设置accessibilityLabel

    我有一个UITableView我内置的loadView 我在做的事情之一loadView是创建一个UIView充当表头并填充UIImageView进去 图像视图包含作为风格化标题的图像 因此我想为 VoiceOver 用户添加辅助功能标签
  • 不要让 IE 选择并复制使用 jQuery .hide() 隐藏的表行

    我在数据表顶部有一个 jQuery 即时搜索栏 所有符合搜索条件的记录都将可见 row show 其余的都是隐藏的 row hide Problem 搜索后 我使用鼠标从搜索结果中选择 复制行列表并将其粘贴到 Excel 中 隐藏 记录也会
  • 使用 CSS 分布内联元素

    有没有一种简单的方法可以使用 CSS 在父块容器中分发内联元素 将边距设置为自动不起作用 因为内联元素之间的边距设置为 0 而且我不想弄乱百分比 因为内容是动态的 特别是 我在段落 p 中有几个锚元素 a 跨越其容器的 80 我正在寻找一种
  • 如何获取TextView的行距?

    有没有办法获得行间距TextView in Android 我尝试寻找fontMetrics of the Paint of the TextView并这样做 tv1 getPaint getFontMetrics pfm float fo
  • 如何在Android中加载大图像并避免内存不足错误?

    我正在开发一个使用大图像的应用程序 1390 870 150kb 50kb 我在点击触发器 ImageView 时添加图像 在某个时刻我遇到内存不足错误 java lang OutOfMemoryError E AndroidRuntime