我正在尝试在Sqlite DB中添加图像并将图像从DB列出到listview ....我正在存储图像路径以获取图像。
当我在设备中列出来自DB的图像时,我收到类似java.lang.OutOfMemoryError: bitmap size exceeds VM budget
我每次都清除堆内存吗? 如何纠正这个..这是我的代码。
LView.class
mySQLiteAdapter = new SQLiteAdapter(this);
mySQLiteAdapter.openToWrite();
mAlbum = (ImageView) findViewById(R.id.iv);
mAlbum.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent intent = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, IMG);
}
});
Button click = (Button) findViewById(R.id.button);
click.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
mySQLiteAdapter.insert(str);
System.out.println(str+" Added");
Intent intent = new Intent(LView.this, MyList.class);
startActivity(intent);
}
});`
`
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode) {
case 1:
if(resultCode == RESULT_OK) {
Uri selectedUri = data.getData();
str = getPath(selectedUri);
Bitmap bitmap;
try {
bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(selectedUri));
mAlbum.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
}
}
// Converting image path Uri to String path to store in DB
public String getPath(Uri uri) {
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cur = managedQuery(uri, projection, null, null, null);
int columnIndex = cur.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cur.moveToFirst();
return cur.getString(columnIndex);
}`
请建议我...... 提前谢谢。
答案 0 :(得分:9)
您可以获得图像的实际大小以防止出现OOM问题。不要先解码图像!!!
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(bitmapByteArray, 0, bitmapByteArray.length, options);'
options.outWidth和options.outHeight就是你想要的。
使用http://hi-android.info/src/com/android/camera/Util.java.html中的以下代码。如果检测到outWidth并且outHeight太大而无法解决OOM问题,只需将outWidth和outHeight设置为较小的大小即可。它将为您提供一个样本大小,解码后的图像将被设置为outWidth和outHeight。此处的位图选项与您在步骤1中使用的相同。
private static int computeInitialSampleSize(BitmapFactory.Options options,
int minSideLength, int maxNumOfPixels) {
double w = options.outWidth;
double h = options.outHeight;
int lowerBound = (maxNumOfPixels == IImage.UNCONSTRAINED) ? 1 :
(int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));
int upperBound = (minSideLength == IImage.UNCONSTRAINED) ? 128 :
(int) Math.min(Math.floor(w / minSideLength),
Math.floor(h / minSideLength));
if (upperBound < lowerBound) {
// return the larger one when there is no overlapping zone.
return lowerBound;
}
if ((maxNumOfPixels == IImage.UNCONSTRAINED) &&
(minSideLength == IImage.UNCONSTRAINED)) {
return 1;
} else if (minSideLength == IImage.UNCONSTRAINED) {
return lowerBound;
} else {
return upperBound;
}
}
获得样本量后,使用它来解码实际图像数据。
options.inTempStorage = new byte[16*1024];
options.inPreferredConfig = (config == null)?BitmapUtil.DEFAULT_CONFIG:config;
options.inSampleSize = BitmapUtil.computeSampleSize(bitmapWidth, bitmapHeight, bitmapWidth < bitmapHeight?targetHeight:targetWidth, bitmapWidth < bitmapHeight?targetWidth:targetHeight, 1);
options.inPurgeable = true;
options.inInputShareable = true;
options.inJustDecodeBounds = false;
options.inDither = true;
result = BitmapFactory.decodeByteArray(bitmapByteArray, 0, bitmapByteArray.length, options);
〜如果这仍然给你OOM问题,你可以尝试降低outWidth和outHeight。 位图使用的是本机堆,而不是java堆。因此很难检测到解码的新图像剩余多少内存。
~~如果你必须设置outWidth和outHeight太低,那么你的代码中可能会有内存泄漏。尝试从你不使用的内存中释放任何对象。
e.g bitmap.release();
~~~以上只是一个示例代码。调整你需要的东西。
答案 1 :(得分:2)
答案 2 :(得分:0)
您是否尝试过使用一个类范围的Bitmap并在case子句中重新分配它?