Bitmap-Bilder optimieren

Wenn Sie nicht vorsichtig sind, können Bilder schnell zu Leistungsproblemen führen. Selbst eine kleine Grafik in einem komprimierten Format wie JPG oder PNG kann sich in eine große Bitmap verwandeln, wenn sie für die Anzeige dekodiert wird.Wenn Sie Grafiken nicht effizient verwenden, können Speicherprobleme auftreten, die die Leistung Ihrer App und anderer Apps auf dem Gerät beeinträchtigen. Mit diesen Best Practices sorgen Sie dafür, dass Ihre App optimal funktioniert.

Bibliotheken zum Laden von Bildern verwenden

Sie können die Effizienz Ihrer App verbessern, indem Sie Bibliotheken zum Laden von Bildern wie Coil (für Kotlin-basierte Projekte) oder Glide (für Java-Projekte) verwenden. Diese Bibliotheken reduzieren die Speichernutzung Ihrer App, indem sie beispielsweise Bilder im Cache speichern, Grafiken bei Bedarf in der Größe anpassen und Grafikobjekte wiederverwenden.

Bilder bei Bedarf in der Größe anpassen

Verwenden Sie die für Ihre Anforderungen geeignete Bildgröße. Sie sollten beispielsweise niemals ein großes Bild in eine kleine Miniaturansicht laden. Verwenden Sie stattdessen eine Methode wie inSampleSize, um eine neu gesampelte Version des Bildes zu laden.

Bibliotheken zum Laden von Bildern wie Coil und Glide übernehmen diese Neuabtastung standardmäßig automatisch für Sie. Sie können die Downsampling-Strategien mit ImageLoader (für Coil) oder DownsampleStrategy (für Glide) konfigurieren.

Alternative Ressourcen für verschiedene Bildschirmgrößen bereitstellen

Wenn Sie Bilder mit Ihrer App ausliefern, sollten Sie Assets in verschiedenen Größen für unterschiedliche Geräteauflösungen bereitstellen. So kann die Downloadgröße Ihrer App auf Geräten reduziert und die Leistung verbessert werden, da auf Geräten mit niedrigerer Auflösung ein Bild mit niedrigerer Auflösung geladen wird. Weitere Informationen zum Bereitstellen alternativer Bitmaps für verschiedene Gerätegrößen finden Sie in der Dokumentation zu alternativen Bitmaps.

Padding nicht direkt anwenden

Manchmal müssen Sie einem Bild Padding hinzufügen. Beispielsweise möchten Sie möglicherweise, dass das Bild von einem transparenten Rahmen umgeben ist, um Letterboxing zu erzielen. In diesen Fällen sollten Sie das Padding nicht direkt dem Bild hinzufügen, da dadurch die Abmessungen des Bildes geändert werden. Lassen Sie stattdessen die Abmessungen des Bildes unverändert, und passen Sie die Position des Bildes auf dem Bildschirm mit InsetDrawable an. Alternativ können Sie dem Composable oder der Ansicht, in dem bzw. der sich das Bild befindet, Padding hinzufügen.

Das richtige Pixelformat auswählen

Wählen Sie das richtige Pixelformat, um ein Gleichgewicht zwischen Speicher und Qualität zu finden. Verwenden Sie RGB_565, wenn Sie keine Transparenz benötigen. Dieses Format benötigt nur halb so viel Speicher wie das Standardformat ARGB_8888.

In Glide können Sie dies mit DecodeFormat konfigurieren. In Coil können Sie die bitmapConfig Eigenschaft verwenden.

Nach Möglichkeit Vektoren verwenden

Bei Bildern, die aus geometrischen Formen bestehen, ist eine Vektorgrafik viel kleiner als eine Bitmap und lässt sich für jede Anzeigedichte reibungslos skalieren. Verwenden Sie nach Möglichkeit Elemente wie ShapeDrawable, um Grafiken darzustellen.

Bitmaps freigeben und wiederverwenden

Große Grafikdateien können viel Speicherplatz belegen. Um die Auswirkungen zu reduzieren, sollten Sie die Grafikobjekte nach Möglichkeit freigeben oder wiederverwenden.

Wenn Sie eine Bibliothek zum Laden von Bildern verwenden, geben Sie Bitmaps für den verwalteten Pool der Bibliothek frei, wenn Sie sie nicht mehr benötigen. Die Bibliothek kann die Objekte bei Bedarf wiederverwenden und einen Speicherpuffer für zukünftige Anforderungen bereithalten.

Wenn Sie Grafiken manuell verwalten, sollten Sie Bitmaps freigeben, wenn Sie sie nicht mehr benötigen. Rufen Sie dazu Bitmap.recycle auf und verwerfen Sie sofort die Bitmap Referenz, anstatt sich auf die automatische Speicherbereinigung zu verlassen.

Weitere Tipps und Tricks

In diesem Abschnitt werden einige weitere Möglichkeiten beschrieben, die Leistung Ihrer App bei der Verarbeitung von Grafiken zu verbessern.

Keine großen Bilder in die AAB-/APK-Datei packen

Eine der Hauptursachen für eine große App-Downloadgröße sind Grafiken, die in der AAB- oder APK-Datei enthalten sind. Verwenden Sie das APK-Analysetool, um sicherzustellen, dass Sie keine größeren Bilddateien als erforderlich verpacken. Reduzieren Sie die Größen oder platzieren Sie die Bilder auf einem Server und laden Sie sie nur bei Bedarf herunter.

Redundante Bitmaps finden

Wenn Sie mehrere Kopien desselben Bildes haben, wird Speicherplatz verschwendet. Mit dem Android Studio-Profiler können Sie redundante Grafiken identifizieren. Verwenden Sie den Heap-Dump Analyzer, um einen Heap-Dump zu erfassen, und filtern Sie die Ergebnisse, indem Sie die Doppelte Bitmaps-Einstellung auswählen.

Bei Verwendung von ImageBitmap vor dem Zeichnen prepareToDraw aufrufen

Wenn Sie ImageBitmap verwenden, rufen Sie ImageBitmap#prepareToDraw() auf, bevor Sie das Bild zeichnen, um den Prozess des Hochladens der Textur auf die GPU zu starten. So kann die GPU die Textur vorbereiten und die Leistung bei der Anzeige eines visuellen Elements auf dem Bildschirm verbessern. Die meisten Bibliotheken zum Laden von Bildern führen diese Optimierung bereits durch. Wenn Sie jedoch selbst mit der Klasse ImageBitmap arbeiten, sollten Sie dies berücksichtigen.

Statt Painter eine Int DrawableRes oder URL als Parameter an Ihr Composable übergeben

Aufgrund der Komplexität des Umgangs mit Bildern (z. B. wäre das Schreiben einer Gleichheits funktion für Bitmaps rechenintensiv) ist die Painter API mit der @Stable Annotation nicht explizit als stabil gekennzeichnet. Instabile Klassen können zu unnötigen Neukompositionen führen, da der Compiler nicht einfach ableiten kann, ob sich die Daten geändert haben.

Daher empfehlen wir, eine URL oder eine ID der zeichenfähigen Ressource als Parameter an Ihre komponierbare Funktion zu übergeben, anstatt einen Painter als Parameter zu übergeben.

// Prefer this:
@Composable
fun MyImage(url: String) {

}
// Over this:
@Composable
fun MyImage(painter: Painter) {

}