我有一个ListView
,每一行都有几个图像按钮。当用户单击列表行时,它将启动一个新的activity。我不得不建立我自己的标签,因为一个问题与相机布局。为获得结果而启动的activity是一张地图。如果我单击按钮启动图像预览(从SD卡上加载图像),应用程序将从activity返回ListView
activity返回到结果处理程序,以重新启动我的新activity,它只不过是一个图像小部件。
在ListView
上的图像预览是通过光标和ListAdapter
完成的。这让它变得很简单,但我不确定如何将一个调整大小的图像(即更小的位大小,而不是像素,作为图像按钮的src
)在飞行中。所以我只是调整了图像的大小,从手机摄像头下来。
问题是,当它试图返回并重新发射第二个activity时,我得到一个OutOfMemoryError
。
这将是更好的,因为我还需要对每行中的小部件/元素的属性进行一些更改,因为由于焦点问题,我无法用触摸屏选择一行。(我会用滚珠。)
当我在ListView
上禁用图像时,它又正常工作了。
附注:我是这样做的:
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.ImageFileName
是ButtonImage
。
这是我的logcat:
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
我在显示图像时还出现了一个新的错误:
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
要修复OutOfMemory错误,您应该执行如下操作:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap preview_bitmap = BitmapFactory.decodeStream(is, null, options);
此insamplesize
选项可减少内存消耗。
这里有一个完整的方法。首先,它读取图像大小而不解码内容本身。然后它找到最佳的insamplesize
值,它应该是2的幂,最后对图像进行解码。
// 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;
}
Android培训课程“高效显示位图”为理解和处理加载位图时的异常java.lang.OutOfMemoryError:位图大小超出VM预算
提供了一些很好的信息。
BitmapFactory
类提供了几种解码方法(DecodeByteArray()
、DecodeFile()
、DecodeSource()
等),用于从各种源创建位图
。根据您的图像数据源选择最合适的解码方法。这些方法试图为构造的位图分配内存,因此很容易导致OutOfMemory
异常。每种类型的decode方法都有附加的签名,可以通过BitmapFactory.options
类指定解码选项。在解码时将injustdecodebounds
属性设置为true
可避免内存分配,为位图对象返回null
但设置outidth
、outtheight
和outmimetype
。该技术允许您在构造(和分配内存)位图之前读取图像数据的维度和类型。
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
异常,请在解码位图之前检查位图的尺寸,除非您绝对相信源能够为您提供大小可预测的图像数据,并且可以轻松地适应可用内存。
既然图像维度已知,就可以使用它们来决定是否应该将完整的图像加载到内存中,或者是否应该加载一个二次采样的版本。以下是一些需要考虑的因素:
例如,如果1024x768像素的图像最终将显示在ImageView
中的128x96像素缩略图中,就不值得将其加载到内存中。
若要告诉解码器对图像进行子采样,将较小的版本加载到内存中,请在BitmapFactory.Options
对象中将insamplesize
设置为true
。例如,一个分辨率为2048x1536的图像,用insamplesize
为4进行解码后,会产生一个大约为512x384的位图。将其加载到内存中使用0.75MB而不是12MB作为完整映像(假设位图配置为argb_8888
)。下面是一种计算样本大小值的方法,该值是基于目标宽度和高度的2的幂:
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;
}
注意:根据insamplesize
文档,计算二次方值是因为解码器通过向下舍入到最接近的二次方来使用最终值。
要使用此方法,首先将InstDecodebounds
设置为True
进行解码,然后通过选项,然后使用新的InSamplesize
值并将InstDecodebounds
设置为False
再次进行解码:
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
中变得很容易,如下面的示例代码所示:
mImageView.setImageBitmap(
decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));
通过根据需要替换适当的bitmapfactory.decode*
方法,您可以遵循类似的过程对来自其他源的位图进行解码。
我在超文本标记语言页面中包含了一个堆叠条形图(带有Chart.js库),可以让用户可视化一些数据。这些数据会随着用户的选择而改变,启用此onClick功能的Javascript函数是: 其中函数createData创建JSON对象(带有标签和数据集)以传递给图形(工作正常),函数makeGrafico(): 获取用于显示的参数的名称,以及上一个函数的JSON对象。 当我第一次单击一个程序时(具有o
我用python scrapy编写了一个脚本,从一个网站下载一些图片。当我运行我的脚本时,我可以在控制台中看到图像的链接(它们都是格式)。然而,当我打开下载完成时应该保存图像的文件夹时,我什么也没有看到。我犯错的地方? 这是我的蜘蛛(我正在从Sublime文本编辑器运行): 这是我在中为要保存的图像定义的内容: 为了让事情更清楚: 我希望保存图像的文件夹名为,我已将其放在项目下的文件夹中。 文件夹
我想在对话框窗口中显示图像(保存在项目文件夹中),但当我运行我的方法showDialogWithImage时,我会得到文件NotFoundException:imgs\pic1。jpg(系统无法找到指定的文件),尽管图像位于那里。 我也尝试过以这种方式加载图像: Image=new Image(getClass(). getResourceAsStream(path));,但遇到了同样的问题。 是
问题内容: 我想在对话框窗口中显示图像(保存在项目文件夹中),但是当我运行方法showDialogWithImage时,我得到FileNotFoundExcpetion:imgs \ pic1.jpg(系统找不到指定的文件),尽管图像位于此处。 我也尝试过以这种方式加载图像: Image image = new Image(getClass()。getResourceAsStream(path))
问题内容: 当有人通过我的应用程序工作时,我正在尝试在后台加载图像。我写的逻辑是这样的: 但是,当我尝试启动这样的新线程时: 但是在程序中我得到错误Looper.prepare必须被调用,随后是逻辑looper.quit() 但是,当我添加Looper.prepare()时,似乎中断了程序,并且没有要调用的looper.quit()。 我是否正确创建任务? 编辑: 这是我尝试运行时的错误日志: 我
错误: 致命异常:main java。java上的lang.NullPointerException。木卫一。文件java上的fixSlashes(File.java:185) 。木卫一。文件(文件:java:134)在ua。罗曼波塔普斯基。安提霍克。普罗卡顿。交付活动。ua的galleryAddPic(DeliverActivity.java:308)。罗曼波塔普斯基。安提霍克。普罗卡顿。交付活