android - 加载图片出现OutOfMemoryException

标签 android bitmap

我想拍照并将它们加载到 ImageView 中,以便我可以切换图片。图片路径保存在数据库中,引用我的项目。所以当我将图片加载到项目中并重新打开项目时,图片仍然可见,因为它们存储在数据库中。

我的问题是,我总是遇到只有 3 张图片的 OutOfMemoryException。我试图将 inSampleSize 连续减小到一个低值。但即使将 inSampleSize 设置为 15,图片的最大数量也可以是 3。

我使用 getAllocationByteCount( ) 为不同的 inSampleSizes 测量了位图的分配大小:

  • 15980544 字节 = 15 MB(示例 1)|| 998784 字节 = 0.95 MB(示例 4)
  • 249696 字节 = 0.23 MB(样本 15)||27744 字节 = 0.02 MB(样本 30)

因为图片旋转了(逆时针旋转 90°),所以我使用 matrix.postRotate(90) 旋转它们,并使用矩阵创建一个新的位图。我用 bitmap.recyle( ) 删除旧位图。新位图的大小为 499392 Byte = 0.47 MB​​

首先我启动一个相机 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( ) 来创建一个图像文件:

    // 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?

最佳答案

当您的应用程序资源超过可用堆内存时,通常会发生内存不足异常。特别是位图使用了更多的内存,并且在达到最大内存并且垃圾收集器开始工作之前它的缓存不会被清除。所以请使用 LruCache 来避免内存不足异常,或者简单地使用库 Universal Image Loader available 从这里。 <强> https://github.com/nostra13/Android-Universal-Image-Loader

关于android - 加载图片出现OutOfMemoryException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24487145/

相关文章:

java - 如何检查上下文当前正在运行的 Activity

android - 如何通过设置首选项更改应用程序的字体大小?

android - 使用大图时如何使用JNI位图操作避免OOM?

android - 加载多个纹理后内存不足

android - 在 ActivityInstrumentationTestCase2 中运行 espresso

android - 22.0.1/aapt”结束,>非零退出值132 [使用android尺寸]

android - multiDexKeepFile 不工作

android - 如何使用位图发送到另一个应用程序

android - 向临时缓存文件android写入和读取位图时出错?

c - CreateCompatibleDC() 是否有必要在一个显示器上使用窗口?