Esistono due modi per pensare alla frase "dimensione heap dell'applicazione disponibile":
Quanto heap può utilizzare la mia app prima che venga attivato un errore grave? E
Quanto heap dovrebbe usare la mia app, dati i vincoli della versione del sistema operativo Android e dell'hardware del dispositivo dell'utente?
Esiste un metodo diverso per determinare ciascuno dei precedenti.
Per l'articolo 1 sopra: maxMemory()
che può essere invocato (ad es. nel onCreate()
metodo della tua attività principale ) come segue:
Runtime rt = Runtime.getRuntime();
long maxMemory = rt.maxMemory();
Log.v("onCreate", "maxMemory:" + Long.toString(maxMemory));
Questo metodo indica quanti byte totali di heap è consentito utilizzare l'app .
Per l'articolo 2 sopra: getMemoryClass()
che può essere invocato come segue:
ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
int memoryClass = am.getMemoryClass();
Log.v("onCreate", "memoryClass:" + Integer.toString(memoryClass));
Questo metodo ti dice approssimativamente quanti megabyte di heap la tua app dovrebbe usare se vuole essere correttamente rispettosa dei limiti del dispositivo attuale e dei diritti di altre app da eseguire senza essere ripetutamente forzata nel onStop()
/ onResume()
ciclo poiché sono maleducati svuotato dalla memoria mentre l'app per elefanti fa il bagno nella vasca idromassaggio Android.
Questa distinzione non è chiaramente documentata, per quanto ne so, ma ho testato questa ipotesi su cinque diversi dispositivi Android (vedi sotto) e ho confermato con mia soddisfazione che questa è un'interpretazione corretta.
Per una versione stock di Android, maxMemory()
in genere restituisce circa lo stesso numero di megabyte indicati in getMemoryClass()
(ovvero circa un milione di volte il secondo valore).
L'unica situazione (di cui sono a conoscenza) per la quale i due metodi possono divergere è su un dispositivo rootato che esegue una versione Android come CyanogenMod, che consente all'utente di selezionare manualmente la dimensione dell'heap che deve essere consentita per ciascuna app. In CM, ad esempio, questa opzione appare sotto "Impostazioni CyanogenMod" / "Prestazioni" / "Dimensione heap VM".
NOTA: CONSIDERARE CHE IMPOSTARE QUESTO VALORE MANUALMENTE PU M ESSERE MESSAGGIO DEL SISTEMA, IN PARTICOLARE se si seleziona un valore inferiore a quello normale per il proprio dispositivo.
Ecco i risultati dei miei test che mostrano i valori restituiti da maxMemory()
e getMemoryClass()
per quattro diversi dispositivi che eseguono CyanogenMod, utilizzando due diversi valori heap (impostati manualmente) per ciascuno:
- G1:
- Con Dimensione heap VM impostata su 16 MB:
- maxMemory: 16777216
- getMemoryClass: 16
- Con Dimensione heap VM impostata su 24 MB:
- maxMemory: 25165824
- getMemoryClass: 16
- Moto Droid:
- Con Dimensione heap VM impostata su 24 MB:
- maxMemory: 25165824
- getMemoryClass: 24
- Con Dimensione heap VM impostata su 16 MB:
- maxMemory: 16777216
- getMemoryClass: 24
- Nexus One:
- Con la dimensione dell'heap di VM impostata su 32 MB:
- maxMemory: 33554432
- getMemoryClass: 32
- Con la dimensione dell'heap di VM impostata su 24 MB:
- maxMemory: 25165824
- getMemoryClass: 32
- Viewsonic GTab:
- Con Dimensione heap VM impostata su 32:
- maxMemory: 33554432
- getMemoryClass: 32
- Con Dimensione heap VM impostata su 64:
- maxMemory: 67108864
- getMemoryClass: 32
Oltre a quanto sopra, ho testato su un tablet Novo7 Paladin con Ice Cream Sandwich. Questa era essenzialmente una versione stock di ICS, tranne per il fatto che ho effettuato il root del tablet attraverso un semplice processo che non sostituisce l'intero sistema operativo, e in particolare non fornisce un'interfaccia che consentirebbe di regolare manualmente le dimensioni dell'heap.
Per quel dispositivo, ecco i risultati:
- Novo7
- maxMemory: 62914560
- getMemoryClass: 60
Inoltre (per Kishore in un commento qui sotto):
- HTC One X
- maxMemory: 67108864
- getMemoryClass: 64
E (per il commento di akauppi):
- Samsung Galaxy Core Plus
- maxMemory: (Non specificato nel commento)
- getMemoryClass: 48
- largeMemoryClass: 128
Per un commento da cmcromance:
- Grande mucchio di Galaxy S3 (Jelly Bean)
- maxMemory: 268435456
- getMemoryClass: 64
E (per i commenti di Tencent):
- LG Nexus 5 (4.4.3) normale
- maxMemory: 201326592
- getMemoryClass: 192
- Heap di grandi dimensioni per LG Nexus 5 (4.4.3)
- maxMemory: 536870912
- getMemoryClass: 192
- Galaxy Nexus (4.3) normale
- maxMemory: 100663296
- getMemoryClass: 96
- Galaxy Nexus (4.3) heap di grandi dimensioni
- maxMemory: 268435456
- getMemoryClass: 96
- Galaxy S4 Play Store Edition (4.4.2) normale
- maxMemory: 201326592
- getMemoryClass: 192
- Heap di grandi dimensioni per Galaxy S4 Play Store Edition (4.4.2)
- maxMemory: 536870912
- getMemoryClass: 192
Altri dispositivi
- Huawei Nexus 6P (6.0.1) normale
- maxMemory: 201326592
- getMemoryClass: 192
Non ho testato questi due metodi usando lo speciale android: largeHeap = opzione manifest "true" disponibile da Honeycomb, ma grazie a cmcromance e tencent abbiamo alcuni valori largeHeap di esempio, come riportato sopra.
La mia aspettativa (che sembra essere supportata dai numeri largeHeap sopra) sarebbe che questa opzione avrebbe un effetto simile all'impostazione manuale dell'heap tramite un sistema operativo rootato, cioè aumenterebbe il valore di maxMemory()
quando si lascia getMemoryClass()
da soli. Esiste un altro metodo, getLargeMemoryClass (), che indica la quantità di memoria consentita per un'app utilizzando l'impostazione largeHeap. La documentazione per getLargeMemoryClass () afferma che "la maggior parte delle applicazioni non dovrebbe aver bisogno di questa quantità di memoria e dovrebbe invece rimanere con il limite getMemoryClass ()."
Se ho indovinato correttamente, l'utilizzo di tale opzione avrebbe gli stessi vantaggi (e pericoli) di quello dello spazio reso disponibile da un utente che ha aumentato l'heap tramite un sistema operativo root (ovvero, se l'app utilizza la memoria aggiuntiva, probabilmente non giocherà altrettanto bene con qualsiasi altra app che l'utente stia eseguendo contemporaneamente).
Sembra che la classe di memoria apparentemente non debba essere un multiplo di 8 MB.
Possiamo vedere da quanto sopra che il getMemoryClass()
risultato è invariato per una data configurazione dispositivo / sistema operativo, mentre il valore maxMemory () cambia quando l'heap è impostato in modo diverso dall'utente.
La mia esperienza pratica è che sul G1 (che ha una classe di memoria di 16), se seleziono manualmente 24 MB come dimensione dell'heap, posso eseguire senza errori anche quando il mio utilizzo della memoria può spostarsi fino a 20 MB (presumibilmente potrebbe andare fino a 24 MB, anche se non ho provato questo). Ma altre app di dimensioni altrettanto grandi potrebbero essere cancellate dalla memoria a causa della porosità della mia app. E, al contrario, la mia app potrebbe essere cancellata dalla memoria se queste altre app ad alta manutenzione vengono portate in primo piano dall'utente.
Pertanto, non è possibile andare oltre la quantità di memoria specificata da maxMemory()
. E, dovresti cercare di rimanere nei limiti specificati da getMemoryClass()
. Un modo per farlo, se tutto il resto fallisce, potrebbe essere quello di limitare la funzionalità di tali dispositivi in modo da preservare la memoria.
Infine, se prevedi di superare il numero di megabyte specificato in getMemoryClass()
, il mio consiglio sarebbe di lavorare a lungo e duramente sul salvataggio e il ripristino dello stato della tua app, in modo che l'esperienza dell'utente sia praticamente ininterrotta se si verifica un onStop()
/ onResume()
ciclo.
Nel mio caso, per motivi di prestazioni, sto limitando la mia app ai dispositivi con 2.2 e versioni successive e ciò significa che quasi tutti i dispositivi che eseguono la mia app avranno una MemoryClass di 24 o superiore. Quindi posso progettare di occupare fino a 20 MB di heap e sono abbastanza fiducioso che la mia app funzionerà bene con le altre app che l'utente potrebbe eseguire contemporaneamente.
Ma ci saranno sempre alcuni utenti rooted che hanno caricato una versione 2.2 o successiva di Android su un dispositivo più vecchio (ad esempio un G1). Quando ti imbatti in una tale configurazione, idealmente, dovresti limitare l'uso della memoria, anche se ti maxMemory()
sta dicendo che puoi andare molto più in alto rispetto ai 16 MB che ti getMemoryClass()
sta dicendo che dovresti mirare. E se non riesci ad assicurarti in modo affidabile che la tua app vivrà entro quel budget, almeno assicurati che onStop()
/ onResume()
funzioni senza problemi.
getMemoryClass()
, come indicato da Diane Hackborn (hackbod) sopra, è disponibile solo di nuovo al livello API 5 (Android 2.0), e quindi, come lei consiglia, puoi supporre che l'hardware fisico di qualsiasi dispositivo che esegue una versione precedente del sistema operativo sia progettato per supportare in modo ottimale le app che occupano uno spazio heap non superiore a 16 MB.
Al contrario, maxMemory()
secondo la documentazione, è disponibile tutto il viaggio di ritorno a livello di API 1. maxMemory()
, su una versione pre-2.0, sarà probabilmente restituire un valore da 16 MB, ma io faccio vedere che nel mio (molto più tardi) le versioni CyanogenMod l'utente può selezionare un valore di heap di soli 12 MB, il che presumibilmente comporterebbe un limite di heap più basso e quindi suggerirei di continuare a testare il maxMemory()
valore, anche per le versioni del sistema operativo precedenti alla 2.0. Potrebbe anche essere necessario rifiutare l'esecuzione nel caso improbabile che questo valore sia impostato anche inferiore a 16 MB, se è necessario disporre di più di quanto maxMemory()
indicato è consentito.