2010-11-07 4 views
16

Ich habe einen Image-Cache in meiner Anwendung, der mit SoftReferences implementiert wird. Dalvik startet Anwendungen mit relativ kleinen Häufchen und erhöht diese dann im Bedarfsfall. Aber ich möchte meine Heap-Größe von Anfang an größer haben. Das liegt daran, dass, wenn ich bereits einige Bilder im Cache habe und eine Aktivität startet (zum Beispiel) oder eine andere Spitzenspeicheranforderung auftritt, mein Cache gelöscht wird, um Speicher für diesen Spitzenbedarf zuzulassen. Als Ergebnis habe ich nach dem Peak noch 2-3 MB freien Speicherplatz, aber mein Cache ist leer!Android: Wie kann die Heap-Größe zur Laufzeit erhöht werden?

Die Lösung, die ich für dieses Problem sehe, ist die Vorverteilung eines größeren Heaps im Vorhinein, so dass selbst bei einem Spitzenverbrauch von 2-3 MBs noch Platz vorhanden ist, sodass meine SoftReferences nicht gelöscht werden.

Ich fand, dass VMRuntime.getRuntime().setMinimumHeapSize(BIGGER_SIZE) wäre hilfreich. Insbesondere verwendet Google das in ihren Apps, wie erwähnt here. Die Klasse VMRuntime ist jedoch als veraltet markiert und soll in einer zukünftigen Version aus der öffentlichen API entfernt werden. So ist setMinimumHeapSize keine dauerhafte Lösung.

Wie also mache ich Dalvik meinen Haufen beim Start zu wachsen?

Derzeit verwende ich eine wirklich geradlinige und käsige Technik, indem ich einfach ein großes Array zuweise und es freigebe. Das lässt Dalvik den Haufen wachsen, wie ich will. Ich bin mir jedoch sicher, dass es eleganter sein muss, das zu tun. Können Sie mir das bitte sagen?

+1

Ich bezweifle, dass Sie einen Weg, dies zu tun, finden die öffentlichen APIs – Falmarri

+0

Google Maps mit verwendet Reflektion und diese api, fand ich diesen Beitrag, während Informationen über den Anruf der Suche :) – sherpya

Antwort

6

Anstatt die Heap-Größe zu erhöhen, können Sie etwas besseres tun. Wie Sie gesagt haben, behalten Sie den Cache in Ihrer Anwendung, die mit SoftReferences implementiert wird. Das Beste ist, LRUCache verwenden Sie etwas wie dies tun können:

private LruCache<String, Bitmap> bitmapCache; 
final int memClass; 
int cacheSize; 

memClass = ((ActivityManager) context.getSystemService(
    Context.ACTIVITY_SERVICE)).getMemoryClass(); 

Return die ungefähre pro Anwendung Speicherklasse des aktuellen Gerätes. Dies gibt Ihnen eine Vorstellung davon, wie schwer ein Speicherlimit für Ihre Anwendung sein sollte, damit das Gesamtsystem am besten funktioniert. Der zurückgegebene Wert ist in Megabyte; Die Baseline-Android-Speicherklasse ist 16 (was zufälligerweise das Java-Heap-Limit dieser Geräte ist); Einige Geräte mit mehr Speicher können 24 oder sogar höhere Nummern zurückgeben.

cacheSize = 1024 * 1024 * memClass/10; 
bitmapCache = new LruCache<String, Bitmap>(cacheSize) { 
    @Override 
    protected int sizeOf(String key, Bitmap value) { 
    return value.getHeight() * value.getRowBytes(); 
} 
}; 

wird es die Bitmap-Bilder von LRUCache zu entfernen, wenn der Speicher der Speicher befinden LRUCache überschreitet und das neue Bild in ihm laden.

0

Ich glaube nicht, dass Sie den Speicher eines Geräts auf dieser Ebene beeinflussen können oder sollen. Lass das System seine Sache machen und nicht dagegen sein. Müssen Sie einen so großen Image-Cache mit SoftReferences halten, auch wenn die Aktivitäten beginnen?

Sie wollen überprüfen, wie es in Regalen erfolgt: siehe Linie 82 in http://code.google.com/p/shelves/source/browse/trunk/Shelves/src/org/curiouscreature/android/shelves/util/ImageUtilities.java?r=26

+1

Ich habe nie gesagt, meine Cache ist groß. In der Tat hängt es nicht von der Cache-Größe ab - selbst mit kleinen Caches wird es nicht funktionieren, wie ich gesagt habe, wegen dieser Speichersprünge. Ich habe einen Cache von ~ 100 Items mit je 2-3KB - das ist kein großer Cache, aber es wird jedes Mal gelöscht. Ich habe festgestellt, dass Garbage Collector in einigen Android-Versionen einen Fehler mit SoftReferences hat: http://stackoverflow.com/questions/4014033 Es macht SoftReference-basierte Caches praktisch nutzlos. – JBM

2

Das Problem ist, dass SoftReferences für Zuweisungen nützlich ist in dem Java-Heap-Speicher gemacht, aber Bilder nativ zugeordnet sind, so dass diese Art Cache funktioniert unter Android nicht wirklich.

+0

Tatsächlich speichern ich Bilder in meinem Cache als Byte-Arrays, wie sie vom Server empfangen werden (der Cache befindet sich auf der Verbindungsebene). Aber trotzdem, es ist ein nützlicher Hinweis - Danke! – JBM

+0

@JBM Wenn Sie sie dort speichern, verwenden Sie tatsächlich den doppelten Arbeitsspeicher, den Sie benötigen, da die Bitmap-Objekte ihre eigenen Bytes verwenden. –

+0

Es ist ein altes Thema, aber ich werde trotzdem antworten. In meinem Fall wird nur eine kleine Anzahl aller vom Server abgerufenen Bilder zu jedem Zeitpunkt angezeigt. Es gibt also keine Doppel-RAM-Nutzung. Tatsächlich verwenden wir einen 2-Level-Cache mit der ersten Ebene auf der Festplatte und den zweiten, kleineren, im Speicher. Meine Frage war, den Speicher zu optimieren. Ich sehe meine Schuld: Ich hätte meine Frage abstrakter stellen sollen; Ich hätte nichts über Server und Bilder sagen sollen, denn das bringt die Leute dazu, in einer Box zu denken. – JBM

4

Wenn der Cache normalerweise klein ist, wie Sie sagen, können Sie selbst einen gültigen Footprint Ihrer App festlegen und Ihren eigenen Cache ohne SoftReferences verwalten.

Zum Beispiel durch einen einfachen Gesamt-Byte-Zähler: Fügen Sie einfach ein beliebiges Element, das oben in einer Liste verwendet wird, hinzu oder verschieben Sie dessen Größe zum Zähler, wenn es neu ist. Löschen Sie von unten, wenn die Gesamtzahl der Bytes Ihr Daumenlimit überschreitet und verringern Sie so Ihren Zähler. Vielleicht ist die Klasse dafür nützlich: Sie kann als Cache wie ein HashMap verwendet werden, aber sie hat eine Reihenfolge wie eine Liste.

1

Sie können die Heap-Größe nicht dynamisch erhöhen.

Sie können anfordern, mehr zu verwenden, indem Sie android: largeHeap = "true" im Manifest, aber Sie können nicht mehr Heap-Größe als normal, da es nur eine Anfrage ist.

können Sie auch nativen Speicher verwenden, so umgehen Sie tatsächlich die Begrenzung der Heap-Größe.

sind hier einige Beiträge ich es gemacht habe:

und hier ist eine Bibliothek i wett gemacht habe: