首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将图像加载到位图对象时出现奇怪的OutOfMemory问题

将图像加载到位图对象时出现奇怪的OutOfMemory问题
EN

Stack Overflow用户
提问于 2009-01-25 03:23:37
回答 43查看 645.1K关注 0票数 1.4K

我有一个ListView,每行都有几个图像按钮。当用户单击列表行时,它将启动一个新的活动。我不得不建立我自己的标签,因为一个问题的相机布局。为结果启动的活动是一张地图。如果单击我的按钮来启动图像预览(从SD卡加载图像),应用程序将从活动返回到ListView活动,返回到结果处理程序,以重新启动我的新活动,这只不过是一个图像小部件。

ListView上的图像预览是用光标和ListAdapter完成的。这使得它非常简单,但我不知道我如何能够把一个调整大小的图像(即更小的比特大小,而不是像src的图像按钮在飞行。所以我就调整了手机摄像头上的图像大小。

问题是我得到了一个OutOfMemoryError,当它试图返回并重新启动第二个活动时。

  • 是否有一种方法可以轻松地逐行构建列表适配器,在那里可以动态地调整大小(按位排列)?

这样做更好,因为我还需要对每一行中的小部件/元素的属性进行一些更改,因为由于焦点问题,我无法选择带有触摸屏的行。(我可以用滚球。)

  • 我知道我可以做一个带外大小调整和保存我的形象,但这不是我真正想要做的,但一些样本代码将是很好的。

一旦我在ListView上禁用了图像,它就会再次正常工作。

菲伊:我就是这样做的:

代码语言:javascript
运行
AI代码解释
复制
String[] from = new String[] { DBHelper.KEY_BUSINESSNAME, DBHelper.KEY_ADDRESS,
    DBHelper.KEY_CITY, DBHelper.KEY_GPSLONG, DBHelper.KEY_GPSLAT,
    DBHelper.KEY_IMAGEFILENAME  + ""};
int[] to = new int[] { R.id.businessname, R.id.address, R.id.city, R.id.gpslong,
    R.id.gpslat, R.id.imagefilename };
notes = new SimpleCursorAdapter(this, R.layout.notes_row, c, from, to);
setListAdapter(notes);

其中R.id.imagefilenameButtonImage

这是我的LogCat:

代码语言:javascript
运行
AI代码解释
复制
01-25 05:05:49.877: ERROR/dalvikvm-heap(3896): 6291456-byte external allocation too large for this process.
01-25 05:05:49.877: ERROR/(3896): VM wont let us allocate 6291456 bytes
01-25 05:05:49.877: ERROR/AndroidRuntime(3896): Uncaught handler: thread main exiting due to uncaught exception
01-25 05:05:49.917: ERROR/AndroidRuntime(3896): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:304)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:149)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:174)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.graphics.drawable.Drawable.createFromPath(Drawable.java:729)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.ImageView.resolveUri(ImageView.java:484)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.ImageView.setImageURI(ImageView.java:281)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.SimpleCursorAdapter.setViewImage(SimpleCursorAdapter.java:183)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.SimpleCursorAdapter.bindView(SimpleCursorAdapter.java:129)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.CursorAdapter.getView(CursorAdapter.java:150)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.AbsListView.obtainView(AbsListView.java:1057)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.ListView.makeAndAddView(ListView.java:1616)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.ListView.fillSpecific(ListView.java:1177)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.ListView.layoutChildren(ListView.java:1454)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.AbsListView.onLayout(AbsListView.java:937)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.view.View.layout(View.java:5611)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.LinearLayout.layoutHorizontal(LinearLayout.java:1108)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.LinearLayout.onLayout(LinearLayout.java:922)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.view.View.layout(View.java:5611)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.FrameLayout.onLayout(FrameLayout.java:294)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.view.View.layout(View.java:5611)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1119)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.LinearLayout.layoutVertical(LinearLayout.java:999)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.LinearLayout.onLayout(LinearLayout.java:920)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.view.View.layout(View.java:5611)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.widget.FrameLayout.onLayout(FrameLayout.java:294)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.view.View.layout(View.java:5611)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.view.ViewRoot.performTraversals(ViewRoot.java:771)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1103)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.os.Handler.dispatchMessage(Handler.java:88)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.os.Looper.loop(Looper.java:123)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at android.app.ActivityThread.main(ActivityThread.java:3742)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at java.lang.reflect.Method.invokeNative(Native Method)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at java.lang.reflect.Method.invoke(Method.java:515)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:497)
01-25 05:05:49.917: ERROR/AndroidRuntime(3896):     at dalvik.system.NativeStart.main(Native Method)
01-25 05:10:01.127: ERROR/AndroidRuntime(3943): ERROR: thread attach failed 

在显示图像时,我还出现了一个新错误:

代码语言:javascript
运行
AI代码解释
复制
22:13:18.594: DEBUG/skia(4204): xxxxxxxxxxx jpeg error 20 Improper call to JPEG library in state %d
22:13:18.604: INFO/System.out(4204): resolveUri failed on bad bitmap uri: 
22:13:18.694: ERROR/dalvikvm-heap(4204): 6291456-byte external allocation too large for this process.
22:13:18.694: ERROR/(4204): VM won't let us allocate 6291456 bytes
22:13:18.694: DEBUG/skia(4204): xxxxxxxxxxxxxxxxxxxx allocPixelRef failed
EN

回答 43

Stack Overflow用户

回答已采纳

发布于 2012-04-12 08:31:31

Android训练类"高效显示位图“为理解和处理异常`java.lang.OutOfMemoryError提供了一些很好的信息:位图大小在加载位图时超出VM预算。

读取位图尺寸和类型

BitmapFactory类提供了几种解码方法(decodeByteArray()decodeFile()decodeResource()等)。用于从各种来源创建Bitmap。根据图像数据源选择最合适的解码方法。这些方法试图为构造的位图分配内存,因此很容易导致OutOfMemory异常。每种类型的解码方法都有额外的签名,可以通过BitmapFactory.Options类指定解码选项。在解码时将inJustDecodeBounds属性设置为true可以避免内存分配,返回位图对象的null,但设置outWidthoutHeightoutMimeType。这种技术允许您在位图的构造(和内存分配)之前读取图像数据的大小和类型。

代码语言:javascript
运行
AI代码解释
复制
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;

为了避免java.lang.OutOfMemory异常,在解码位图之前检查它的大小,除非您绝对信任源为您提供可预测大小的图像数据,这些数据非常适合可用内存。

将缩小版本加载到内存中。

现在,图像维数已经知道,它们可以用来决定是否应该将整个映像加载到内存中,或者是否应该加载次采样版本。以下是一些需要考虑的因素:

  • 估计在内存中加载完整图像的内存使用量。
  • 考虑到应用程序的任何其他内存需求,您愿意承诺加载此映像的内存量。
  • 要加载到的目标ImageView或UI组件的维度。
  • 当前设备的屏幕大小和密度。

例如,如果1024x768像素图像最终显示在ImageView中的128x96像素缩略图中,它就不值得加载到内存中。

要让解码器对图像进行子采样,将较小的版本加载到内存中,请将inSampleSize设置为BitmapFactory.Options对象中的true。例如,以inSampleSize为4解码的分辨率2048x1536的图像产生大约512x384的位图。将其加载到内存中使用的是0.75MB,而不是整个映像的12 of (假设ARGB_8888的位图配置)。下面是一种基于目标宽度和高度计算两个幂的样本大小值的方法:

代码语言:javascript
运行
AI代码解释
复制
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 / 2;
        final int halfWidth = width / 2;

        // 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;
}

Note:计算两个值的幂是因为解码器使用最后一个值,根据inSampleSize文档,将其舍入到最接近的二次方。

要使用此方法,首先将inJustDecodeBounds设置为true, pass the options through and then decode again using the new true, pass the options through and then decode again using the new

代码语言:javascript
运行
AI代码解释
复制
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
    int reqWidth, int reqHeight) {

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

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

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

这种方法可以轻松地将任意大尺寸的位图加载到显示100x100像素缩略图的ImageView中,如下面的示例代码所示:

代码语言:javascript
运行
AI代码解释
复制
mImageView.setImageBitmap(
    decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));

您可以遵循类似的过程从其他来源解码位图,方法是根据需要替换适当的BitmapFactory.decode*方法。

票数 688
EN

Stack Overflow用户

发布于 2009-05-05 01:00:14

要修复OutOfMemory错误,您应该执行如下操作:

代码语言:javascript
运行
AI代码解释
复制
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap preview_bitmap = BitmapFactory.decodeStream(is, null, options);

inSampleSize选项减少内存消耗。

这是一个完整的方法。首先,它读取图像大小而不解码内容本身。然后找出最佳的inSampleSize值,以2为幂,最后对图像进行解码。

代码语言:javascript
运行
AI代码解释
复制
// Decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f) {
    try {
        // Decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(new FileInputStream(f), null, o);

        // The new size we want to scale to
        final int REQUIRED_SIZE=70;

        // Find the correct scale value. It should be the power of 2.
        int scale = 1;
        while(o.outWidth / scale / 2 >= REQUIRED_SIZE && 
              o.outHeight / scale / 2 >= REQUIRED_SIZE) {
            scale *= 2;
        }

        // Decode with inSampleSize
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = scale;
        return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
    } catch (FileNotFoundException e) {}
    return null;
}
票数 918
EN

Stack Overflow用户

发布于 2010-08-23 07:25:32

我对Fedor的代码做了一个小小的改进。它基本上是这样做的,但没有(在我看来)丑陋的while循环,它总是产生一个2的幂。对于Fedor做出最初的解决方案,我非常赞赏,直到我找到了他的解决方案,然后我才能做出这样的解决方案:)

代码语言:javascript
运行
AI代码解释
复制
 private Bitmap decodeFile(File f){
    Bitmap b = null;

        //Decode image size
    BitmapFactory.Options o = new BitmapFactory.Options();
    o.inJustDecodeBounds = true;

    FileInputStream fis = new FileInputStream(f);
    BitmapFactory.decodeStream(fis, null, o);
    fis.close();

    int scale = 1;
    if (o.outHeight > IMAGE_MAX_SIZE || o.outWidth > IMAGE_MAX_SIZE) {
        scale = (int)Math.pow(2, (int) Math.ceil(Math.log(IMAGE_MAX_SIZE / 
           (double) Math.max(o.outHeight, o.outWidth)) / Math.log(0.5)));
    }

    //Decode with inSampleSize
    BitmapFactory.Options o2 = new BitmapFactory.Options();
    o2.inSampleSize = scale;
    fis = new FileInputStream(f);
    b = BitmapFactory.decodeStream(fis, null, o2);
    fis.close();

    return b;
}
票数 383
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/477572

复制
相关文章
Python3中get与post请求
urllib.request 模块定义了一些类及方法,用于帮助我们访问URL urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False) 方法是用来打开url的方法,其中url可以是一个合法的url字符串,或者是一个request对象;data必须是字节数据类型的。详细介绍可参见python3官方文档urllib.request。 关于数据提交的两种方式get、post的
听城
2018/04/27
1.5K0
使用OpenCV和Python计算视频中的总帧数
本文来自光头哥哥的博客【Count the total number of frames in a video with penCV and Python】,仅做学习分享。
周旋
2020/10/23
3.8K0
使用OpenCV和Python计算视频中的总帧数
接口测试如何在post请求中传递文件
2.找到body这个选项,输入文件对应的参数名,在然后把参数名后面的text选择为file。
sik1
2022/06/21
3.6K0
【小家Java】Servlet规范之---请求(request):Servlet中如何获取POST请求参数?(使用getParameter())
request对象封装了来自客户端的所有请求信息。在HTTP协议中,客户端发给服务端的所有信息都是通过request对象的请求头和请求体来传送的。
YourBatman
2019/09/03
14.1K0
【小家Java】Servlet规范之---请求(request):Servlet中如何获取POST请求参数?(使用getParameter())
直接取出 post 请求中的 json、得请求体参数、查看 post 请求参数
方法如下: try{ ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = requestAttributes.getRequest(); StringBuffer sb = new S
微风-- 轻许--
2022/04/13
5.1K0
python使用request发送post请求
唯一Chat
2023/09/15
3350
python post请求
post请求只需构建一个Request对象,并把参数传递给Request对象的data属性即可(也可以在urlopen方法中传递给data参数)。
灯珑LoGin
2022/10/31
1.9K0
http请求中get和post方法的区别
一般我们在浏览器输入一个网址访问网站都是GET请求;再FORM表单中,可以通过设置Method指定提交方式为GET或者POST提交方式,默认为GET提交方式。
用户7880705
2020/11/06
5.1K0
SpringMVC源码分析:POST请求中的文件处理
本章我们来一起阅读和分析SpringMVC的部分源码,看看收到POST请求中的二进制文件后,SpingMVC框架是如何处理的;
程序员欣宸
2020/02/13
1.6K0
Gatsby 中怎么加载使用视频文件?
一、简介 Gatsby 项目中怎么播放视频? 二、解决方案 1、HTML5 <video> 使用 HTML5 的 video 标签,播放 本地视频 和 远程视频。 import * as React from 'react' import dog from '../assets/dog.mp4' const VideoShow = () => { return ( <div> <video width="70%" controls>
Learn-anything.cn
2021/12/02
7420
Qt中实现http服务接收POST请求
总体而言,HTTP服务器适用于传统的客户端-服务器通信,每次请求都需要重新建立连接,适合请求响应式的场景。WebSocket服务器适用于需要实时双向通信的场景,适合聊天应用、实时数据更新等。
Linux兵工厂
2023/09/15
1.6K0
Qt中实现http服务接收POST请求
Python爬虫中:get和post方法使用
requests库是一个常用于http请求的模块,性质是和urllib,urllib2是一样的,作用就是向指定目标网站的后台服务器发起请求,并接收服务器返回的响应内容。
Python学习者
2023/02/16
1.2K0
python 异步post请求
import aiohttp headers = {'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 6.0.1; Nexus 5 Build/MMB29K) tuhuAndroid 5.24.6', 'content-type': 'application/json'} async with aiohttp.ClientSession(headers=headers) as sess:
Wyc
2021/08/13
3.6K0
POST请求实践--视频演示
讲完get,轮到post请求了,本期分享了post请求的实现,分享了一些参数依赖的情况。录制过程中翻车了好几次,各位见谅。
FunTester
2020/03/23
5220
HTTP协议中的GET、POST请求方法的区别
HTTP 请求方法有:HEAD、PUT、DELETE、OPTIONS、CONNECT
宣言言言
2019/12/15
5.1K0
OpenCV中OpenMP的使用
作者:gnuhpc 出处:http://www.cnblogs.com/gnuhpc/
流川疯
2019/01/18
1.6K0
Node中POST请求的正确处理方式
Node的 http 模块只对HTTP报文的头部进行了解析,然后触发 request 事件。如果请求中还带有内容部分(如 POST 请求,它具有报头和内容),内容部分需要用户自行接收和解析。
Qiang
2019/06/20
2.1K0
Node中POST请求的正确处理方式
如何使用OpenCV在Python中访问IP摄像头
首先,必须找出网址流是什么。通过在构造函数中提供摄像机的网址流,可以在OpenCV中访问IP摄像机cv2.VideoCapture。可以使用某些网络扫描实用程序(例如在linux上的arp-scan)找到摄像机的IP地址。网址进一步的细节,如Protocol,Credentials和Channel应该可以在相机说明书或软件/手机应用程序中找到。我们通过在网络上搜索相机的型号来找到相机的网址流。
小白学视觉
2020/09/14
6.9K0
防止页面url缓存中 ajax中post 请求的处理方式
一般我们在开发中经常会用到Ajax请求,异步发送请求,然后获取我们想要的数据,在Ajax中使用Get请求数据不会有页面缓存的问题,而使用POST请求可是有时候页面会缓存我们提交的信息,导致我们发送的异步请求不能正确的返回我们想要的数据,那么遇到这种情况,我们应该怎么办呢???
全栈程序员站长
2022/07/19
1.6K0
点击加载更多

相似问题

为什么jQuery remove不适用于动态添加的行?

20

Jquery不适用于动态添加的DIVS

24

JQuery .remove()不适用于动态添加的元素

21

jQuery插件不适用于动态添加的元素

48

jQuery .on()事件不适用于动态添加的元素

36
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档