[Si noti che (come illustrato da CommonsWare di seguito) l'intero approccio in questa risposta si applica solo al 2.3.x (Gingerbread). A partire da Honeycomb I dati bitmap vengono allocati nell'heap della VM.]
I dati bitmap non sono allocati nell'heap della VM. C'è un riferimento ad esso nell'heap della VM (che è piccolo), ma i dati reali sono allocati nell'heap nativo dalla libreria grafica Skia sottostante.
Sfortunatamente, mentre la definizione di BitmapFactory.decode ...() dice che restituisce null se i dati dell'immagine non possono essere decodificati, l'implementazione di Skia (o piuttosto la colla JNI tra il codice Java e Skia) registra il messaggio che stai vedendo ("VM non ci permetterà di allocare byte xxxx") e poi lancia un'eccezione OutOfMemory con il messaggio fuorviante "dimensione bitmap supera il budget VM".
Il problema non si trova nell'heap della VM ma piuttosto nell'heap nativo. L'heap nativo è condiviso tra le applicazioni in esecuzione, quindi la quantità di spazio libero dipende da quali altre applicazioni sono in esecuzione e dal loro utilizzo di bitmap. Ma, dato che BitmapFactory non tornerà, hai bisogno di un modo per capire se la chiamata avrà successo prima di farcela.
Ci sono routine per monitorare la dimensione dell'heap nativo (vedere i metodi getNative della classe Debug). Tuttavia, ho trovato che getNativeHeapFreeSize() e getNativeHeapSize() non sono affidabili. Quindi in una delle mie applicazioni che crea dinamicamente un gran numero di bitmap faccio quanto segue.
La dimensione dell'heap nativo varia in base alla piattaforma.Quindi all'avvio, controlliamo la dimensione massima dell'heap della VM consentita per determinare la dimensione massima consentita dell'heap nativo. [I numeri magici sono stati determinati dai test su 2.1 e 2.2, e possono essere diversi su altri livelli API.]
long mMaxVmHeap = Runtime.getRuntime().maxMemory()/1024;
long mMaxNativeHeap = 16*1024;
if (mMaxVmHeap == 16*1024)
mMaxNativeHeap = 16*1024;
else if (mMaxVmHeap == 24*1024)
mMaxNativeHeap = 24*1024;
else
Log.w(TAG, "Unrecognized VM heap size = " + mMaxVmHeap);
Poi ogni volta che abbiamo bisogno di chiamare BitmapFactory che precedono la chiamata da un controllo della forma.
long sizeReqd = bitmapWidth * bitmapHeight * targetBpp/8;
long allocNativeHeap = Debug.getNativeHeapAllocatedSize();
if ((sizeReqd + allocNativeHeap + heapPad) >= mMaxNativeHeap)
{
// Do not call BitmapFactory…
}
Nota che il heapPad è un numero magico per tener conto del fatto che: a) la segnalazione di dimensione heap nativo è "soft" e b) vogliamo lasciare un po 'di spazio nel mucchio nativo per altre applicazioni. Al momento stiamo lavorando con un pad 3 * 1024 * 1024 (cioè 3Mbytes).
[questo] (http://stackoverflow.com/questions/477572/android-strange-out-of-memory-issue-while-loading-an-image-to-a-mapmap-object/14731953#14731953) posso aiutare! –