Es gibt zwei Möglichkeiten, über Ihren Ausdruck "Größe des Anwendungsheaps verfügbar" nachzudenken:
Wie viel Heap kann meine App verwenden, bevor ein schwerer Fehler ausgelöst wird? Und
Wie viel Heap sollte meine App angesichts der Einschränkungen der Android-Betriebssystemversion und der Hardware des Geräts des Benutzers verwenden?
Es gibt eine andere Methode zur Bestimmung der oben genannten.
Für Punkt 1 oben: maxMemory()
Dies kann onCreate()
wie folgt aufgerufen werden (z. B. in der Methode Ihrer Hauptaktivität ):
Runtime rt = Runtime.getRuntime();
long maxMemory = rt.maxMemory();
Log.v("onCreate", "maxMemory:" + Long.toString(maxMemory));
Diese Methode gibt an, wie viele Heap- Bytes Ihre App insgesamt verwenden darf .
Für Punkt 2 oben: getMemoryClass()
die wie folgt aufgerufen werden kann:
ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
int memoryClass = am.getMemoryClass();
Log.v("onCreate", "memoryClass:" + Integer.toString(memoryClass));
Diese Methode gibt ungefähr an, wie viele Megabyte Heap Ihre App verwenden sollte , wenn die Grenzen des aktuellen Geräts und die Rechte anderer Apps zur Ausführung beachtet werden sollen, ohne wiederholt in den onStop()
/ onResume()
-Zyklus gezwungen zu werden, da diese grob sind Der Speicher wird gelöscht, während Ihre Elefanten-App im Android-Whirlpool badet.
Diese Unterscheidung ist meines Wissens nicht eindeutig dokumentiert, aber ich habe diese Hypothese auf fünf verschiedenen Android-Geräten getestet (siehe unten) und zu meiner eigenen Zufriedenheit bestätigt, dass dies eine korrekte Interpretation ist.
Bei einer Standardversion von Android maxMemory()
wird normalerweise ungefähr die gleiche Anzahl von Megabyte zurückgegeben, wie in angegeben getMemoryClass()
(dh ungefähr eine Million Mal der letztere Wert).
Die einzige Situation (von der ich weiß), in der die beiden Methoden voneinander abweichen können, ist ein gerootetes Gerät, auf dem eine Android-Version wie CyanogenMod ausgeführt wird. Auf diese Weise kann der Benutzer manuell auswählen, wie groß ein Heap für jede App sein soll. In CM wird diese Option beispielsweise unter "CyanogenMod-Einstellungen" / "Leistung" / "VM-Heap-Größe" angezeigt.
HINWEIS: BEACHTEN SIE, DASS DIE MANUELLE EINSTELLUNG DIESES WERTES IHR SYSTEM MESSEN KANN, INSBESONDERE, wenn Sie einen kleineren Wert als für Ihr Gerät normal auswählen.
Hier sind meine Testergebnisse, die die von maxMemory()
und getMemoryClass()
für vier verschiedene Geräte mit CyanogenMod zurückgegebenen Werte zeigen , wobei jeweils zwei verschiedene (manuell eingestellte) Heap-Werte verwendet werden:
- G1:
- Bei einer VM-Heap-Größe von 16 MB:
- maxMemory: 16777216
- getMemoryClass: 16
- Bei einer VM-Heap-Größe von 24 MB:
- maxMemory: 25165824
- getMemoryClass: 16
- Moto Droid:
- Bei einer VM-Heap-Größe von 24 MB:
- maxMemory: 25165824
- getMemoryClass: 24
- Bei einer VM-Heap-Größe von 16 MB:
- maxMemory: 16777216
- getMemoryClass: 24
- Nexus Eins:
- Bei einer VM-Heap-Größe von 32 MB:
- maxMemory: 33554432
- getMemoryClass: 32
- Bei einer VM-Heap-Größe von 24 MB:
- maxMemory: 25165824
- getMemoryClass: 32
- Viewsonic GTab:
- Bei VM-Heap-Größe auf 32:
- maxMemory: 33554432
- getMemoryClass: 32
- Mit VM Heap Size auf 64 eingestellt:
- maxMemory: 67108864
- getMemoryClass: 32
Darüber hinaus habe ich auf einem Novo7 Paladin-Tablet mit Ice Cream Sandwich getestet. Dies war im Wesentlichen eine Standardversion von ICS, mit der Ausnahme, dass ich das Tablet durch einen einfachen Prozess gerootet habe, der nicht das gesamte Betriebssystem ersetzt und insbesondere keine Schnittstelle bietet, über die die Heap-Größe manuell angepasst werden kann.
Für dieses Gerät sind hier die Ergebnisse:
- Novo7
- maxMemory: 62914560
- getMemoryClass: 60
Auch (per Kishore in einem Kommentar unten):
- HTC ein x
- maxMemory: 67108864
- getMemoryClass: 64
Und (laut Akauppis Kommentar):
- Samsung Galaxy Core Plus
- maxMemory: (Nicht im Kommentar angegeben)
- getMemoryClass: 48
- largeMemoryClass: 128
Per Kommentar von cmcromance:
- Galaxy S3 (Jelly Bean) großer Haufen
- maxMemory: 268435456
- getMemoryClass: 64
Und (Kommentare von Tencent):
- LG Nexus 5 (4.4.3) normal
- maxMemory: 201326592
- getMemoryClass: 192
- LG Nexus 5 (4.4.3) großer Haufen
- maxMemory: 536870912
- getMemoryClass: 192
- Galaxy Nexus (4.3) normal
- maxMemory: 100663296
- getMemoryClass: 96
- Galaxy Nexus (4.3) großer Haufen
- maxMemory: 268435456
- getMemoryClass: 96
- Galaxy S4 Play Store Edition (4.4.2) normal
- maxMemory: 201326592
- getMemoryClass: 192
- Galaxy S4 Play Store Edition (4.4.2) großer Haufen
- maxMemory: 536870912
- getMemoryClass: 192
Andere Geräte
- Huawei Nexus 6P (6.0.1) normal
- maxMemory: 201326592
- getMemoryClass: 192
Ich habe diese beiden Methoden nicht mit dem speziellen Android getestet: largeHeap = "true" Manifestoption, die seit Honeycomb verfügbar ist, aber dank cmcromance und tencent haben wir einige Beispielwerte für largeHeap, wie oben angegeben.
Meine Erwartung (die durch die oben genannten LargeHeap-Zahlen unterstützt zu werden scheint) wäre, dass diese Option einen ähnlichen Effekt hat wie das manuelle Festlegen des Heaps über ein verwurzeltes Betriebssystem - dh den Wert von erhöht, maxMemory()
während Sie in getMemoryClass()
Ruhe lassen. Es gibt eine andere Methode, getLargeMemoryClass (), die angibt, wie viel Speicher für eine App mit der Einstellung largeHeap zulässig ist. In der Dokumentation zu getLargeMemoryClass () heißt es: "Die meisten Anwendungen sollten nicht so viel Speicher benötigen und stattdessen das Limit getMemoryClass () einhalten."
Wenn ich richtig geraten habe, hätte die Verwendung dieser Option dieselben Vorteile (und Gefahren) wie die Verwendung des Speicherplatzes, der von einem Benutzer bereitgestellt wird, der den Heap über ein verwurzeltes Betriebssystem erhöht hat (dh wenn Ihre App den zusätzlichen Speicher verwendet). Es wird wahrscheinlich nicht so gut mit allen anderen Apps gespielt, die der Benutzer gleichzeitig ausführt.
Beachten Sie, dass die Speicherklasse anscheinend kein Vielfaches von 8 MB sein muss.
Aus dem getMemoryClass()
Obigen können wir ersehen, dass das Ergebnis für eine bestimmte Geräte- / Betriebssystemkonfiguration unverändert bleibt, während sich der Wert für maxMemory () ändert, wenn der Heap vom Benutzer anders festgelegt wird.
Meine eigene praktische Erfahrung ist, dass ich auf dem G1 (mit einer Speicherklasse von 16), wenn ich manuell 24 MB als Heap-Größe auswähle, ohne Fehler ausgeführt werden kann, selbst wenn meine Speichernutzung auf 20 MB ansteigen darf (vermutlich könnte dies der Fall sein) bis zu 24 MB hoch gehen, obwohl ich das noch nicht ausprobiert habe). Aber andere ähnlich große Apps werden möglicherweise aufgrund der Schweinerei meiner eigenen App aus dem Speicher gelöscht. Umgekehrt wird meine App möglicherweise aus dem Speicher gelöscht, wenn diese anderen wartungsintensiven Apps vom Benutzer in den Vordergrund gerückt werden.
Sie können also nicht die von angegebene Speichermenge überschreiten maxMemory()
. Und Sie sollten versuchen , innerhalb der von angegebenen Grenzen zu bleiben getMemoryClass()
. Eine Möglichkeit, dies zu tun, besteht darin, die Funktionalität solcher Geräte so einzuschränken, dass Speicherplatz gespart wird, wenn alles andere fehlschlägt.
Wenn Sie vorhaben, die in angegebene Anzahl von Megabyte zu überschreiten getMemoryClass()
, würde ich Ihnen raten, lange und intensiv am Speichern und Wiederherstellen des Status Ihrer App zu arbeiten, damit die Benutzererfahrung praktisch nicht unterbrochen wird, wenn ein onStop()
/ onResume()
Zyklus auftritt.
In meinem Fall beschränke ich meine App aus Leistungsgründen auf Geräte mit 2.2 und höher. Dies bedeutet, dass fast alle Geräte, auf denen meine App ausgeführt wird, eine Speicherklasse von 24 oder höher haben. So kann ich bis zu 20 MB Heap belegen und bin mir ziemlich sicher, dass meine App mit den anderen Apps, die der Benutzer möglicherweise gleichzeitig ausführt, gut funktioniert.
Es wird jedoch immer einige Root-Benutzer geben, die eine Android-Version 2.2 oder höher auf ein älteres Gerät (z. B. ein G1) geladen haben. Wenn Sie eine solche Konfiguration auftreten, im Idealfall sollten Sie Ihre Speichernutzung abspecken, auch wenn maxMemory()
Ihnen sagt , dass Sie viel höher als die 16MB gehen können , die getMemoryClass()
Ihnen sagt , dass Sie sollten Targeting werden. Und wenn Sie nicht zuverlässig sicherstellen können, dass Ihre App innerhalb dieses Budgets lebt, stellen Sie zumindest sicher, dass onStop()
/ onResume()
nahtlos funktioniert.
getMemoryClass()
Wie von Diane Hackborn (hackbod) oben angegeben, ist sie nur ab API-Level 5 (Android 2.0) verfügbar. Sie können daher davon ausgehen, dass die physische Hardware aller Geräte, auf denen eine frühere Version des Betriebssystems ausgeführt wird, ausgelegt ist um Apps optimal zu unterstützen, die einen Heap-Speicherplatz von nicht mehr als 16 MB belegen.
Im Gegensatz dazu maxMemory()
wird gemäß der Dokumentation, die ganzen Weg zurück auf API - Ebene 1 zur Verfügung steht maxMemory()
, auf einer Pre-2.0 - Version wird wahrscheinlich gibt einen 16MB Wert, aber ich tue , dass in meinen (viel später) CyanogenMod Versionen der Benutzer Sie können einen Heap-Wert von nur 12 MB auswählen, was vermutlich zu einer niedrigeren Heap-Grenze führen würde. Daher würde ich vorschlagen, dass Sie den maxMemory()
Wert auch für Versionen des Betriebssystems vor 2.0 weiter testen . In dem unwahrscheinlichen Fall, dass dieser Wert sogar auf weniger als 16 MB festgelegt ist, müssen Sie möglicherweise sogar die Ausführung verweigern, wenn Sie mehr als maxMemory()
angegeben benötigen .