2013-06-11 17 views
16

Sto scrivendo un'applicazione per galleria di immagini e continuo a riscontrare errori di memoria insufficienti. Memorizzo tutte le mie immagini in cache ma il problema si verifica quando provo a passare tra le immagini veramente veloce. Suppongo che l'app stia allocando la memoria più velocemente di quanto il GC abbia il tempo di liberarli (perché il crash non avviene quando cambio le immagini lentamente).android: largeHeap = convenzione "true"?

Dopo aver sbattuto la testa contro questo problema per giorni, ho finalmente deciso di provare l'impostazione largeHeap nel file manifest. Dopo questa impostazione, la mia app non si blocca più a prescindere dalla velocità di passaggio tra le immagini.

Ora, voglio sapere se c'è qualche convenzione o linea guida generale per usare l'impostazione largeHeap perché probabilmente non avrebbe molto senso se, diciamo, una nota che prendesse app usata largeHeap. In generale, quali app sono un buon candidato per l'impostazione largeHeap?

Grazie

+0

BTW, se si chiama 'bitmap.recycle();' appena si è SICURO di non utilizzare nuovamente una bitmap, la maggior parte della memoria di tale bitmap verrà immediatamente liberata. (Quando il GC si avvicina, tutto ciò che rimane è un piccolo oggetto.) – ToolmakerSteve

risposta

23

in generale, ciò che le applicazioni sono un buon candidato per l'impostazione largeHeap?

quelli in cui si può giustificare all'utente perché si sta costringendo tutte le loro altre applicazioni di memoria, per offrirti una quantità fuori misura lo spazio di heap.

Personalmente, non considererei "un'app Galleria immagini" per qualificarsi. AutoCAD, editor di video e simili si qualificherebbero.

Per quanto riguarda i problemi di gestione della memoria, assicurarsi che si sta utilizzando inBitmap su BitmapOptions durante il funzionamento a livello di API 11+, in modo da riciclare buffer esistenti piuttosto che passare attraverso la raccolta dei rifiuti. In particolare per una galleria di immagini, dove probabilmente ci sono un sacco di dimensioni delle miniature abbastanza costanti, il riciclaggio dei buffer esistenti sarà un enorme vantaggio. Ciò può aiutare sia il consumo complessivo di memoria (cioè, si è veramente senza memoria) e la frammentazione della memoria (ad esempio, si ottiene un OutOfMemoryError con un sacco di spazio heap, ma nessun blocco singolo abbastanza grande per la propria allocazione, a causa del "frakkin" di Android immondizia compattatrice).

Si potrebbe anche considerare di considerare le implementazioni di cache di immagini esistenti, come quella che ha Picasso, per vedere se ci sono alcuni suggerimenti che si potrebbero imparare (o eventualmente solo riutilizzare).

+0

Grazie per la risposta! Una domanda: sto anche costruendo un'app gallery, ma sto già utilizzando Picasso e sto ancora utilizzando OutOfMemoryError. Quale pensi sia la cosa migliore da fare? L'uso di 'largeHeap = true' risolve questo problema; pensi che ci siano altre cose che posso fare oltre a usare questa soluzione rapida? – Karim

+3

@Cookiki: "Quale pensi che sia la cosa migliore da fare?" - Scopri qual è il tuo vero problema. Hai una perdita di memoria? Non stai riutilizzando gli oggetti 'Bitmap' dove potresti? E così via. – CommonsWare

1

Innanzitutto, assicurarsi di non caricare bitmap più grandi del necessario:
Load a Scaled Down Version into Memory.


Poi, prima di provare largeHeap, cercano di liberare la memoria rapidamente da soli:

Se si chiama bitmap.recycle(); non appena si è certi di non usare di nuovo una bitmap, quindi la maggior parte di quel la memoria bitmap sarà immediatamente liberata. (Quando il GC fa il giro, tutto ciò che rimane è un oggetto minuscolo.)


sulle versioni più recenti di Android, ci sono alternative (invece di recycle) che possono essere più efficaci:
Managing Bitmap Memory

Personalmente, io uso ancora recycle spesso, specialmente se potrei essere il caricamento di un diverso dimensione immagine, quindi non può reuse quello esistente. Inoltre, trovo più semplice codificare lo "scarico" dei vecchi media separatamente dal "caricamento" dei nuovi media, quando si passa a un altro frammento o attività:
Come lasciare il vecchio frammento, tutte le vecchie immagini bitmap I recycle (quindi, se raggiungibile da un campo statico, impostare su null).


La regola generale per se utilizzare largeHeap, è quello di considerare che dopo che hai provato modi alternativi per ridurre l'utilizzo della memoria.

Codice vostra applicazione in modo da potrebbe girarlo di nuovo, e ancora correre.

Ad esempio, monitor your memory usage e carico "ridimensionati" bitmap se la memoria è stretto. L'utente noterà davvero se una determinata immagine non è in risoluzione "retina" del proprio dispositivo?

Oppure, se si tratta di un dispositivo più vecchio, più lento, sarà largeHeap rendere la vostra app non risponde/a scatti? In tal caso, è possibile eliminare ulteriormente la risoluzione o mostrare un numero inferiore di bitmap contemporaneamente?

Porta la tua app a funzionare in tutte le circostanze, senzalargeHeap [con le tecniche sopra menzionate]. NOTA: è possibile eseguire il "force-test" sulla memoria limitata allocando alcuni bitmap "fittizi" e conservare i riferimenti nei campi globali, in modo che non vengano liberati.

ora siete in grado di valutare il trade-off, in quanto colpisce la vostra applicazione:

Quando non accende largeHeap in poi, utilizzare la vostra applicazione pesantemente - sono lì luoghi dove è ora "più lenta", o le animazioni "balbettano" o altrimenti sembrano meno lisce? ASSICURARSI DI ESEGUIRE SU ALMENO UN DISPOSITIVO ANZIANO E SU UN DISPOSITIVO HIGH_RESOLUTION. A causa dell'heap più grande, potresti vedere tempi lunghi del GC.

OPPURE potresti concludere che largeHeap sta funzionando bene per te, e ora puoi tranquillamente dire che è la scelta migliore nella tua circostanza.

Problemi correlati