2010-12-28 16 views
18

HI in meiner anwendung ich habe fotos videos etc, im fall von bild ich habe die skalierung, aber ich bekomme out of memory ausnahme in manchmal, wie kann ich mit dem aus speicher Ausnahme effizient.android wie man aus dem speicher ausnahme

+0

Es ist OutOfMemory 'Fehler' nicht' Ausnahme'. Es gibt einen großen Unterschied zwischen "Error" und "Exception" –

Antwort

28

Überprüfen Sie, ob die Bildgröße kleiner als der verfügbare Speicher ist, bevor Sie versuchen, sie zu laden. Die effizienteste Methode zur Behandlung von OutOfMemoryException besteht also darin, Ihre Anwendung so zu strukturieren, dass sie niemals versucht, viele Daten in den Speicher zu laden, um die Ausnahme zu vermeiden.

12

OutOfMemory kann nicht verarbeitet werden. Was denken Sie?

Der Speicher des Geräts ist voll, Sie haben die Ausnahme und dann magisch etwas tun, die die Ausnahme entfernen und Sie haben jetzt mehr Heap. Das ist unmöglich, weißt du?

OutOfMemory muss verhindert werden, nicht nach Auftreten behandelt werden.

+20

verdammt klingt das so intensiv –

+4

Wahrscheinlich die Mehrheit der Fälle, wo man ein OutOfMemory bekommt, beinhalten Bitmap-Laden (wie in dieser Frage) und es ist einfach nicht wahr, dass es nichts gibt tun können. In vielen Fällen können Sie kein N-Megabyte-Bild laden, aber Sie können immer noch ein N/4-Megabyte-Bild laden. Verwenden Sie BitmapFactory.Optionen mit einer inSampleSize> = 1, und tun inSampleSize * = 2 vor jeder Wiederholung. –

+19

Eigentlich ist dieser Beitrag falsch. Der Gerätespeicher ist NICHT unbedingt voll. Ein OutOfMemory tritt auf, wenn die angeforderte Speichermenge nicht zugewiesen werden kann. Wenn 40 MB verfügbar sind und Sie versuchen, 45 MB zuzuweisen, erhalten Sie OutOfMemory, aber Sie haben immer noch 40 MB zur Verfügung. – xtempore

8

Es gibt a method in Activity, die aufgerufen wird, wenn das Gerät knapp wird, aber dies kann nur zum Auslösen der Cache-Dateien Reinigung verwendet werden. Dies bedeutet nicht, dass Ihr Anwendungsprozess nicht mehr ausreicht.

Sie könnten auch einen try catch-Block hinzufügen, um Error oder OutOfMemoryError abzufangen, aber das wäre zu spät.

Die Handhabung einer großen Anzahl von Bitmaps oder großen Bitmaps ist wirklich schwierig in Android-Anwendungen. Sie finden einige Tipps zu diesem Thema in this article von Romain Guy.

Sie können auch Bitmaps direkt auf die Auflösung laden, die Sie benötigen, indem Sie eine Stichprobengröße in BitmapFactory.options angeben, die Sie für BitmapFactory.decode *() -Methoden bereitstellen.

+1

Beachten Sie, dass onLowMemory nur aufgerufen wird, wenn eine andere Anwendung mehr Arbeitsspeicher benötigt. Nicht, wenn Ihre Anwendung nicht genügend Arbeitsspeicher hat. So wird onLowMemory nicht aufgerufen, wenn OutOfMemoryError ausgelöst wird. – Robert

2

Ich habe begonnen, diese Routine zu versuchen, die ein JPEG in ein ImageView lädt und nach nicht genügend Speicher sucht und neu skaliert, bis es passt.

static public boolean tryJpegRead(ImageView imageView, File fn){ 
if (!fn.exists()){ 
    Log.d("ANDRO_ASYNC",String.format("missing file %s",fn.getAbsolutePath())); 
    return false; 
} 
BitmapFactory.Options o = new BitmapFactory.Options(); 
    for (int i = 1; i<10; i++){ 
     o.inSampleSize = i; 
     o.inJustDecodeBounds = true; 
     BitmapFactory.decodeFile(fn.getAbsolutePath(), o); 
     int h = o.outHeight; 
     int w = o.outWidth; 
     Log.d("ANDRO_ASYNC",String.format("going in h=%d w=%d resample = %d",h,w,o.inSampleSize)); 
     o.inJustDecodeBounds = false; 
     try{ 
      imageView.setImageBitmap(
       Bitmap.createScaledBitmap(
         BitmapFactory.decodeFile(fn.getAbsolutePath(), o), 
         w, 
         h, 
         true)); 
      return true; // only happens when there is no error 
     }catch(OutOfMemoryError E){ 
      Log.d("ANDRO_ASYNC",String.format("catch Out Of Memory error")); 
    //  E.printStackTrace(); 
      System.gc(); 
     }   
    } 
    return false; 
} 
+0

Die Idee ist nett. Fügt es Latenz hinzu? – drulabs

2

Wenn mit OutOfMemory Fehlern zu tun Manipulation in Bitmap, um die Größe der entschlüsselten Bitmap Überprüfung ist die beste und so weit ich weiß, nur Option. Code folgt:

public static BitmapFactory.Options getBitmapOptionsWithoutDecoding(String url){ 
    BitmapFactory.Options opts = new BitmapFactory.Options(); 
    opts.inJustDecodeBounds = true; 
    BitmapFactory.decodeFile(url, opts); 
    return opts; 
} 

public static int getBitmapSizeWithoutDecoding(String url){ 
    BitmapFactory.Options opts = getBitmapOptionsWithoutDecoding(url); 
    return opts.outHeight*opts.outWidth*32/(1024*1024*8); 
} 

//ref:http://stackoverflow.com/questions/6073744/android-how-to-check-how-much-memory-is-remaining 
public static double availableMemoryMB(){ 
    double max = Runtime.getRuntime().maxMemory()/1024; 
    Debug.MemoryInfo memoryInfo = new Debug.MemoryInfo(); 
    Debug.getMemoryInfo(memoryInfo); 
    return (max - memoryInfo.getTotalPss())/1024; 
} 

public static final long SAFETY_MEMORY_BUFFER = 10;//MB 

public static boolean canBitmapFitInMemory(String path){ 
    long size = getBitmapSizeWithoutDecoding(path); 
    Log.d(TAG, "image MB:"+size); 
    return size <= availableMemoryMB() - SAFETY_MEMORY_BUFFER; 
} 

ref: http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

2

Falls Sie haben große Bilder wie Hintergründe oder ähnliches, eine einfache Möglichkeit, Nicht genügend Arbeitsspeicher zu verhindern, ist es, Bilder von ziehbar-xhdpi zu ziehbar-nodpi zu bewegen, aber passen Sie auf, das wird die Bitmap ohne jede Änderung laden. Die gute Art und Weise sollte BitmapFactory.options verwendet werden, um Ihre Notwendigkeit

0
try { 
// All methods here.... 
} catch(OutOfMemoryException e){ 
// Show an AlertDialog with "Memory is full" title 
// If press ok then starts the process again.. 
} 
1

Verwenden Android zu passen: allowBackup = "true", android: hardwareAccelerated = "false" und Android: largeHeap = "true" für dieses Problem lösen

<application 
     android:allowBackup="true" 
     android:icon="@mipmap/ic_launcher" 
     android:label="@string/app_name" 
     android:roundIcon="@mipmap/ic_launcher" 
     android:hardwareAccelerated="false" 
     android:largeHeap="true" 
     android:theme="@style/AppTheme"> 
Verwandte Themen