我想拍照并将它们加载到imageview中,以便我可以切换图片。图片路径保存在数据库中,该数据库提供给我的项目。因此,当我将图片加载到项目中并重新打开项目时,图片仍然可见,因为它们存储在数据库中。
我的问题是,我总是遇到只有3张图片的OutOfMemoryException。我试图将inSampleSize减少到一个低值的连续性。但即使inSampleSize为15,最大图片数量也可以是3。
我使用getAllocationByteCount( )
为不同的inSampleSizes测量了位图的分配大小:
由于图片是旋转的(逆时针90°),我用matrix.postRotate(90)
旋转它们,并用矩阵创建一个新的位图。我用bitmap.recyle( )
删除旧位图。新位图的大小为499392字节= 0.47 MB
首先,我开始使用Camera Intent:
// capturePicture( ) soll die Kamera starten und ein neues Bild soll gemacht werden können
private void capturePicture() {
// erstelle einen neuen Intent, damit sich die Kamera öffnet
// mit MediaStore.ACTION_IMAGE_CAPTURE wird angewiesen die Kamera zu starten
CameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Sicherstellen, dass auf dem Handy eine Kamera installiert ist
if (CameraIntent.resolveActivity(getPackageManager()) != null) {
photoFile = null;
try {
// rufe die Methode createImageFile( ) auf, damit die Aufnahme in eine Datei gespeichert werden kann
photoFile = createImageFile();
} catch (IOException ex) {
// wenn das Erstellen des Bildes fehlschlug
Toast.makeText(thisActivity,"Bilddatei konnte nicht erstellt werden",
Toast.LENGTH_LONG).show();
}
// wenn es eine Datei gibt, soll diese in der ImageView angezeigt werden
if (photoFile != null) {
CameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
// rufe die onActivityForResult( ) Methode mit einer ID auf, um das Bild in der ImageView anzeigen zu können
this.savePicture(photoFile.getAbsolutePath(), photoFile.getName());
startActivityForResult(CameraIntent, REQUEST_TAKE_PHOTO);
//bitmap.recycle();
//System.gc();
this.reloadPicDB();
}
} else {
// TODO: auf den Play Store mit einer Kamera App verweisen
Toast.makeText(thisActivity,"Sie haben leider keine Kamera installiert", Toast.LENGTH_SHORT).show();
}
photoCount++;
}
在这个方法中,我调用方法createImageFile( )
来创建一个Imagefile:
// erstellt eine Datei nachdem ein Foto gemacht wurde und gibt diese zurück
private File createImageFile() throws IOException {
// TODO: Sinnvollen Dateinamen für die Bilddateien geben
//String timeStamp = new SimpleDateFormat("ddMMyyyy_HHmmss").format(new Date());
imageFileName = "JPEGNEU";
// TODO: überlegen, wohin die Bilddateien gespeichert werden sollen
//File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File pictureStorageDir = new File("/sdcard/neu/");
// In der Datei pictureImage werden der Name, Endung und Verzeichnis gespeichert
File pictureImage = File.createTempFile(imageFileName, /* prefix */
".jpg", /* suffix */
pictureStorageDir /* directory */
);
// ermittle den absoluten Pfad der Bilddatei und speichere diesen in den String PhotoPath
PhotoPath = pictureImage.getAbsolutePath();
// gebe die Bilddatei zurück, damit dieses in der Methode capturePicture weiter verwendet werden kann
return pictureImage;
}
图片将以onActivityResult( )
方式显示:
if(requestCode == REQUEST_TAKE_PHOTO){
ImageView beispiel = (ImageView) findViewById(R.id.beispiel);
BitmapFactory.Options options1 = new BitmapFactory.Options();
options1.inSampleSize = 15; //1/12 des Bildes zu laden
options1.inPreferredConfig = Config.ARGB_4444;
Bitmap image = BitmapFactory.decodeFile(PhotoPath, options1);
Log.d("Speicherausgabe", "Speicherausgabe0.1 " + image.getAllocationByteCount());
Matrix matrix = new Matrix();
matrix.postRotate(90);
bitmap = Bitmap.createBitmap(image, 0, 0, image.getWidth() , image.getHeight(), matrix, true);
image.recycle();
System.gc();
if(zaehlerRequestPhoto == 0){
beispiel.setImageBitmap(bitmap);
} else {
beispiel.setImageBitmap(bitmap);
Log.d("Speicherausgabe", "Speicherausgabe3 " + bitmap.getAllocationByteCount());
//System.gc();
}
在这种情况下,我该怎么做才能避免OutOfMemoryException?
答案 0 :(得分:1)
当您的应用程序资源超出可用堆内存时,通常会发生内存不足异常。特别是位图使用更多内存,并且在达到最大内存并且垃圾收集器完成其工作之前,其缓存不会被清除。因此,请使用LruCache避免内存不足或仅使用库中的通用映像加载器。的 https://github.com/nostra13/Android-Universal-Image-Loader 强>
答案 1 :(得分:1)
准备好图像后,您应该回收并将其置为空,如下所示:
image.recycle();
image=null;
OR
您还可以通过添加到AndroidManifest来增加堆空间:
<application
android:label="@string/app_name"
android:largeHeap="true"
...
答案 2 :(得分:0)
我在Here
之前提出了这个问题但是我仍然无法完全解决问题,但是由于@Binh Tran能够通过以下代码降低强度
public Bitmap decodeSampledBitmapFromResourceMemOpt(
InputStream inputStream, int reqWidth, int reqHeight) {
byte[] byteArr = new byte[0];
byte[] buffer = new byte[1024];
int len;
int count = 0;
try {
while ((len = inputStream.read(buffer)) > -1) {
if (len != 0) {
if (count + len > byteArr.length) {
byte[] newbuf = new byte[(count + len) * 2];
System.arraycopy(byteArr, 0, newbuf, 0, count);
byteArr = newbuf;
}
System.arraycopy(buffer, 0, byteArr, count, len);
count += len;
}
}
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(byteArr, 0, count, options);
options.inSampleSize = calculateInSampleSize(options, reqWidth,
reqHeight);
options.inPurgeable = true;
options.inInputShareable = true;
options.inJustDecodeBounds = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
int[] pids = { android.os.Process.myPid() };
MemoryInfo myMemInfo = mAM.getProcessMemoryInfo(pids)[0];
Log.e(TAG, "dalvikPss (decoding) = " + myMemInfo.dalvikPss);
return BitmapFactory.decodeByteArray(byteArr, 0, count, options);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
The method that does the calculation:
public void onButtonClicked(View v) {
int[] pids = { android.os.Process.myPid() };
MemoryInfo myMemInfo = mAM.getProcessMemoryInfo(pids)[0];
Log.e(TAG, "dalvikPss (beginning) = " + myMemInfo.dalvikPss);
long startTime = System.currentTimeMillis();
FileInputStream inputStream;
String filePath = Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/test2.png";
File file = new File(filePath);
try {
inputStream = new FileInputStream(file);
// mBitmap = decodeSampledBitmapFromResource(inputStream, 800, 800);
mBitmap = decodeSampledBitmapFromResourceMemOpt(inputStream, 800,
800);
ImageView imageView = (ImageView) findViewById(R.id.image);
imageView.setImageBitmap(mBitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
myMemInfo = mAM.getProcessMemoryInfo(pids)[0];
Log.e(TAG, "dalvikPss (after all) = " + myMemInfo.dalvikPss
+ " time = " + (System.currentTimeMillis() - startTime));
}