Speicherauslastung optimieren

Die Arbeitsspeicheroptimierung ist entscheidend für eine reibungslose Leistung, um App-Abstürze zu verhindern und die System- und Plattformstabilität aufrechtzuerhalten. Die Speichernutzung sollte in jeder App überwacht und optimiert werden. Inhalts-Apps für Fernseher stellen jedoch spezielle Herausforderungen dar, die sich von denen typischer Android-Apps für Mobilgeräte unterscheiden.

Ein hoher Arbeitsspeicherverbrauch kann zu Problemen mit dem App- und Systemverhalten führen, z. B.:

  • Die App selbst kann langsam oder verzögert werden oder im schlimmsten Fall beendet werden.
  • Nutzersichtbare Systemdienste (Lautstärkeregelung, Steuerfeld für Bildeinstellungen, Sprachassistent usw.) reagieren sehr verzögert oder funktionieren möglicherweise gar nicht.
  • Systemkomponenten können beendet werden. Diese Komponenten werden dann neu gestartet, was zu extremen Ressourcenkonflikten führt und sich direkt auf die App im Vordergrund auswirkt.
  • Der Übergang zum Launcher kann sich erheblich verzögern und die App im Vordergrund reagiert erst wieder, wenn der Übergang abgeschlossen ist.
  • Das System kann in eine direkte Rückforderung gelangen, bei der die Ausführung eines Threads vorübergehend pausiert wird, während auf die Speicherzuweisung gewartet wird. Das kann bei jedem Thread passieren, z. B. beim Haupt- oder Codec-bezogenen Thread, was zu Audio- und Videoframe-Ausfällen und UI-Störungen führen kann.

Speicheranforderungen auf Fernsehern

Fernseher haben in der Regel deutlich weniger Arbeitsspeicher als Smartphones oder Tablets. Eine Konfiguration, die wir beispielsweise auf einem Fernseher sehen können, ist 1 GB RAM und 1080p-Videoauflösung. Gleichzeitig haben die meisten TV-Apps ähnliche Funktionen, daher eine ähnliche Implementierung und gemeinsame Herausforderungen. In diesen beiden Fällen treten Probleme auf, die bei anderen Gerätetypen und Apps nicht auftreten:

  • Media-TV-Apps bestehen in der Regel sowohl aus Rasteransichten als auch aus Vollbildhintergrundbildern, für die in kurzer Zeit viele Bilder in den Arbeitsspeicher geladen werden müssen.
  • In TV-Apps werden Multimediastreams abgespielt, für die eine bestimmte Menge an Arbeitsspeicher für die Video- und Audiowiedergabe zugewiesen werden muss. Außerdem sind erhebliche Medienpuffer erforderlich, um eine flüssige Wiedergabe zu ermöglichen.
  • Zusätzliche Medienfunktionen wie Suchfunktionen, Folgenwechsel oder Audiotrackwechsel können den Arbeitsspeicher belasten, wenn sie nicht richtig implementiert sind.

TV-Geräte

In diesem Leitfaden geht es hauptsächlich um die Arbeitsspeichernutzung und Arbeitsspeicherziele von Apps auf Geräten mit wenig RAM.

Berücksichtige bei Fernsehern die folgenden Eigenschaften:

  • Gerätespeicher: Die Größe des Arbeitsspeichers (RAM), der auf dem Gerät installiert ist.
  • Auflösung der Geräte-UI: Die Auflösung, mit der das Gerät das Betriebssystem und die Anwendungs-UI rendert. Sie ist in der Regel niedriger als die Videoauflösung des Geräts.
  • Videoauflösung: Die maximale Auflösung, mit der Videos auf dem Gerät wiedergegeben werden können.

Dies führt zur Kategorisierung verschiedener Gerätetypen und dazu, wie der Arbeitsspeicher von ihnen verwendet werden sollte.

Fernsehgeräte – Zusammenfassung

Gerätespeicher Videoauflösung des Geräts Auflösung der Geräte-UI isLowRAMDevice()
1 GB 1080p 720p Ja
1,5 GB 2160p 1080p Ja
≥ 1,5 GB 1080p 720p oder 1080p Nein*
≥ 2 GB 2160p 1080p Nein*

Fernsehgeräte mit wenig RAM

Diese Geräte befinden sich in einer Situation mit Arbeitsspeichermangel und melden ActivityManager.isLowRAMDevice() als „wahr“. Bei Anwendungen, die auf Fernsehern mit wenig RAM ausgeführt werden, müssen zusätzliche Maßnahmen zur Arbeitsspeicherverwaltung implementiert werden.

Geräte mit den folgenden Merkmalen fallen in diese Kategorie:

  • 1 GB: 1 GB RAM, Benutzeroberfläche mit einer Auflösung von 720p/HD (1.280 x 720), Videoauflösung von 1080p/FullHD (1.920 x 1.080)
  • 1,5 GB: 1,5 GB RAM, Benutzeroberfläche mit 1080p/FullHD (1.920 x 1.080) Auflösung, Videoauflösung 2160p/UltraHD/4K (3.840 x 2.160)
  • Andere Situationen, in denen der OEM das Flag ActivityManager.isLowRAMDevice() aufgrund zusätzlicher Arbeitsspeichereinschränkungen definiert hat.

Normale Fernsehgeräte

Auf diesen Geräten ist der Speicherdruck nicht so hoch. Wir gehen davon aus, dass diese Geräte die folgenden Eigenschaften haben:

  • Mindestens 1,5 GB RAM, 720p- oder 1080p-Benutzeroberfläche und 1080p-Videoauflösung
  • ≥ 2 GB RAM, 1080p-Benutzeroberfläche und 1080p- oder 2160p-Videoauflösung

Das bedeutet jedoch nicht, dass sich Apps nicht um die Speichernutzung auf diesen Geräten kümmern sollten, da bestimmte Speichernutzungen den verfügbaren Speicher dennoch erschöpfen und die Leistung beeinträchtigen können.

Speicherziele auf Fernsehern mit wenig RAM

Wenn Sie den Arbeitsspeicher auf diesen Geräten messen, empfehlen wir dringend, jeden Bereich des Arbeitsspeichers mit dem Android Studio Memory Profiler zu überwachen. TV-Apps sollten ihre Arbeitsspeichernutzung analysieren und dafür sorgen, dass ihre Kategorien unter den in diesem Abschnitt definierten Grenzwerten liegen.

Speicher-Profiler

Im Abschnitt So wird Arbeitsspeicher gezählt finden Sie eine detaillierte Erklärung der angegebenen Arbeitsspeicherwerte. Bei der Definition von Grenzwerten für TV-Apps konzentrieren wir uns auf drei Speicherkategorien:

  • Anonymous + Swap: Besteht aus Java-, Native- und Stack-Allokationsspeicher in Android Studio.
  • Grafik: Wird direkt im Profiler-Tool erfasst. Sie bestehen in der Regel aus Grafiktexturen.
  • Datei: In Android Studio werden Fehler in den Kategorien „Code“ und „Sonstiges“ gemeldet.

Anhand dieser Definitionen wird in der folgenden Tabelle der maximale Wert für jede Art von Speichergruppe angegeben:

Arbeitsspeichertyp Zweck Nutzungsziele (1 GB)
Anonymous + Swap (Java + Native + Stack) Wird für Zuweisungen, Medien-Puffer, Variablen und andere speicherintensive Aufgaben verwendet. < 160 MB
Grafik Wird von der GPU für Texturen und Display-bezogene Buffers verwendet 30–40 MB
Datei Wird für Codeseiten und Dateien im Arbeitsspeicher verwendet. 60–80 MB

Der maximale Gesamtspeicher (Anonymous+Auslagerung + Grafik + Datei) darf Folgendes nicht überschreiten:

  • 280 MB Arbeitsspeichernutzung insgesamt (Anon+Swap + Grafik + Datei) für Geräte mit 1 GB RAM.

Die folgenden Werte sollten dringend nicht überschritten werden:

  • 200 MB Arbeitsspeichernutzung (Anon+Swap + Graphics).

Dateispeicher

Allgemeine Hinweise zum speichergestützten Arbeitsspeicher:

  • Im Allgemeinen wird der Dateispeicher durch die Arbeitsspeicherverwaltung des Betriebssystems gut verwaltet.
  • Wir haben derzeit keine Hinweise darauf gefunden, dass dies eine Hauptursache für die Arbeitsspeicherauslastung ist.

Im Allgemeinen gilt jedoch Folgendes:

  • Fügen Sie Ihrem Build keine nicht verwendeten Bibliotheken hinzu und verwenden Sie nach Möglichkeit kleine Teilmengen von Bibliotheken anstelle der vollständigen Bibliotheken.
  • Lassen Sie große Dateien nicht im Arbeitsspeicher geöffnet und geben Sie sie frei, sobald Sie sie nicht mehr benötigen.
  • Minimieren Sie die Größe des kompilierten Codes für Java- und Kotlin-Klassen. Weitere Informationen finden Sie im Leitfaden App verkleinern, verschleieren und optimieren.

Spezifische TV-Empfehlungen

Dieser Abschnitt enthält konkrete Empfehlungen zur Optimierung der Speichernutzung auf Fernsehern.

Grafikspeicher

Verwenden Sie geeignete Bildformate und Auflösungen.

  • Laden Sie keine Bilder mit einer höheren Auflösung als die Auflösung der Geräteoberfläche hoch. So sollten beispielsweise 1080p-Bilder auf einem Gerät mit einer 720p-Benutzeroberfläche auf 720p verkleinert werden.
  • Verwenden Sie nach Möglichkeit hardwaregestützte Bitmaps.
    • Aktivieren Sie in Bibliotheken wie Glide die Funktion Downsampler.ALLOW_HARDWARE_CONFIG, die standardmäßig deaktiviert ist. Wenn Sie diese Option aktivieren, werden Bitmaps nicht dupliziert, die sich sonst sowohl im Grafik- als auch im anonymen Arbeitsspeicher befinden würden.
  • Vermeiden Sie Zwischen- und Neu-Renderings.
    • Diese können mit dem Android GPU-Prüfer identifiziert werden:
    • Suchen Sie im Bereich „Texturen“ nach Bildern, die Schritte auf dem Weg zum endgültigen Rendering sind, anstatt nur die Elemente zu zeigen, aus denen sie bestehen. Dies ist in der Regel ein sogenanntes „Zwischen-Rendering“.
    • Bei Android SDK-Anwendungen können Sie diese häufig entfernen, indem Sie mit dem Layout-Flag forceHasOverlappedRendering:false Zwischenrender für dieses Layout deaktivieren.
    • Weitere Informationen zu sich überschneidenden Rendern findest du unter Überschneidende Render vermeiden.
  • Lade nach Möglichkeit keine Platzhalterbilder, sondern verwende @android:color/ oder @color für Platzhaltertexturen.
  • Kombinieren Sie nicht mehrere Bilder auf dem Gerät, wenn die Komposition auch offline ausgeführt werden könnte. Laden Sie lieber eigenständige Bilder hoch, anstatt Bilder aus heruntergeladenen Bildern zu erstellen.
  • In der Anleitung Bitmaps verarbeiten erfahren Sie, wie Sie Bitmaps besser verarbeiten.

Anon+Swap-Speicher

Anon+Swap besteht aus Native + Java + Stack-Zuweisungen im Android Studio-Speicher-Profiler. Verwende ActivityManager.isLowMemoryDevice(), um zu prüfen, ob das Gerät Speichermangel hat, und passe dich dieser Situation an. Beachte dabei die folgenden Richtlinien.

  • Medien:
    • Geben Sie eine variable Größe für Medien-Puffer an, die vom RAM des Geräts und der Auflösung der Videowiedergabe abhängt. Das sollte für eine Minute Videowiedergabe ausreichen:
      1. 40–60 MB für 1 GB / 1080p
      2. 60–80 MB für 1,5 GB / 1080p
      3. 80–100 MB für 1,5 GB / 2160p
      4. 100–120 MB für 2 GB / 2160p
    • Freigabe von Medienspeicher beim Wechseln einer Folge, um eine Erhöhung der Gesamtmenge des anonymen Arbeitsspeichers zu verhindern.
    • Löschen und beenden Sie Medienressourcen sofort, wenn Ihre App angehalten wird: Verwenden Sie die Lebenszyklus-Callbacks der Aktivität, um Audio- und Videoressourcen zu verwalten. Wenn es sich nicht um eine Audio-App handelt, beenden Sie die Wiedergabe, wenn onStop() bei Ihren Aktivitäten auftritt, speichern Sie alle ausgeführten Aktionen und legen Sie fest, dass Ihre Ressourcen freigegeben werden sollen. Sie können Aufgaben planen, die Sie später benötigen. Weitere Informationen finden Sie im Abschnitt Jobs und Benachrichtigungen.
    • Achten Sie beim Suchen nach Videos auf den Arbeitsspeicher des Buffers: Entwickler reservieren oft zusätzliche 15 bis 60 Sekunden an zukünftigen Inhalten, um das Video für den Nutzer bereitzuhalten. Dies führt jedoch zu zusätzlichem Arbeitsspeicheraufwand. Im Allgemeinen sollte der Puffer nicht länger als 5 Sekunden sein, bis der Nutzer die neue Videoposition ausgewählt hat. Wenn du beim Suchen unbedingt zusätzliche Zeit im Voraus puffern musst, beachte Folgendes:
      • Weise den Suchpuffer vorab zu und verwende ihn wieder.
      • Die Puffergröße sollte maximal 15–25 MB betragen (je nach Gerätespeicher).
  • Zuweisungen:
    • Folgen Sie der Anleitung zum Grafikspeicher, um zu verhindern, dass Bilder im anonymen Speicher dupliziert werden.
      • Bilder belegen oft den größten Speicherplatz. Daher kann das Duplizieren von Bildern das Gerät stark belasten. Das gilt insbesondere bei intensiver Navigation in Bildrasteransichten.
    • Zuweisungen freigeben, indem Sie ihre Verweise beim Wechseln von Bildschirmen löschen: Achten Sie darauf, dass keine Verweise auf Bitmaps und Objekte zurückbleiben.
  • Bibliotheken:
    • Profilieren Sie die Speicherzuweisungen von Bibliotheken, wenn Sie neue hinzufügen, da möglicherweise auch zusätzliche Bibliotheken geladen werden, die wiederum Zuweisungen vornehmen und Bindungen erstellen.
  • Networking:
    • Führen Sie beim Starten der App keine blockierenden Netzwerkaufrufe aus. Sie verlangsamen den Start der Anwendung und verursachen beim Start zusätzlichen Arbeitsspeicher-Overhead, da der Arbeitsspeicher durch die App-Auslastung besonders begrenzt ist. Zeigen Sie zuerst einen Ladebildschirm oder einen Startbildschirm an und senden Sie Netzwerkanfragen, sobald die Benutzeroberfläche eingerichtet ist.

Bindungen

Bindungen führen zu zusätzlichem Arbeitsspeicher-Overhead, da sie andere Anwendungen in den Arbeitsspeicher aufnehmen oder den Arbeitsspeicherverbrauch der verknüpften App erhöhen (falls sie sich bereits im Arbeitsspeicher befindet), um den API-Aufruf zu erleichtern. Dadurch wird der verfügbare Arbeitsspeicher für die App im Vordergrund reduziert. Achten Sie beim Binden eines Dienstes darauf, wann und wie lange Sie die Bindung verwenden. Lösen Sie die Bindung, sobald sie nicht mehr benötigt wird.

Typische Bindungen und Best Practices:

  • Play Integrity API: Wird verwendet, um die Geräteintegrität zu prüfen.
    • Geräteintegrität nach dem Ladebildschirm und vor der Medienwiedergabe prüfen
    • Lösen Sie Verweise auf PlayIntegrity StandardIntegrityManager, bevor Inhalte wiedergegeben werden.
  • Play Billing Library: Wird zum Verwalten von Abos und Käufen über Google Play verwendet.
  • GMS FontsProvider
    • Verwenden Sie auf Geräten mit wenig RAM lieber eigenständige Schriftarten als einen Schriftartenanbieter, da das Herunterladen der Schriftarten kostenintensiv ist und FontsProvider Dienste dafür bindet.
  • Google Assistant-Bibliothek: Wird manchmal für die Suche und die In-App-Suche verwendet. Ersetzen Sie diese Bibliothek nach Möglichkeit.
    • Für Leanback-Apps: Verwenden Sie die Gboard-Sprachausgabe oder die androidx.leanback-Bibliothek.
      • Beachten Sie die Richtlinien für die Suche.
      • Hinweis: leanback wird eingestellt und Apps sollten auf TV Compose umgestellt werden.
    • Für Compose-Apps:
      • Verwenden Sie die Gboard-Sprachausgabe, um die Sprachsuche zu implementieren.
    • Implementieren Sie Als Nächstes ansehen, um Medieninhalte in Ihrer App sichtbar zu machen.

Dienste im Vordergrund

Dienste im Vordergrund sind eine spezielle Art von Dienst, die mit einer Benachrichtigung verknüpft ist. Diese Benachrichtigung wird auf Smartphones und Tablets im Benachrichtigungs- bzw. Infobereich angezeigt. Fernseher haben jedoch keinen Infobereich in diesem Sinne. Auch wenn Dienste im Vordergrund nützlich sind, weil sie auch dann ausgeführt werden können, wenn die Anwendung im Hintergrund läuft, müssen TV-Apps die folgenden Richtlinien einhalten:

Unter Android TV und Google TV dürfen Dienste im Vordergrund nur dann weiter ausgeführt werden, wenn der Nutzer die App verlässt:

  • Für Audio-Apps:Dienste im Vordergrund dürfen nur dann weiter ausgeführt werden, wenn der Nutzer die App verlässt, damit der Audiotrack weiter abgespielt wird. Der Dienst muss sofort nach Ende der Audiowiedergabe beendet werden.
  • Bei allen anderen Apps:Alle Dienste im Vordergrund müssen beendet werden, sobald der Nutzer die App verlässt, da der Nutzer nicht benachrichtigt wird, dass die App noch ausgeführt wird und Ressourcen verbraucht.
  • Verwende WorkManager für Hintergrundjobs wie das Aktualisieren von Empfehlungen oder Videoempfehlungen.

Aufgaben und Wecker

WorkManager ist die moderne Android API zum Planen wiederkehrender Hintergrundjobs. WorkManager verwendet den neuen Status JobScheduler, wenn er verfügbar ist (SDK 23 und höher), andernfalls den alten Status AlarmManager. Beachten Sie die folgenden Best Practices für die Ausführung geplanter Jobs auf dem Fernseher:

  • Verwenden Sie die AlarmManager APIs unter SDK 23 und höher nicht, insbesondere AlarmManager.set(), AlarmManager.setExact() und ähnliche Methoden. Sie ermöglichen es dem System nicht, den richtigen Zeitpunkt für die Ausführung der Jobs zu bestimmen (z. B. wenn das Gerät inaktiv ist).
  • Führen Sie auf Geräten mit wenig RAM Jobs nur aus, wenn dies unbedingt erforderlich ist. Verwende WorkManager WorkRequest nur zum Aktualisieren von Empfehlungen nach der Wiedergabe und versuche, dies zu tun, während die App noch geöffnet ist.
  • Definieren Sie WorkManager Constraints, damit das System Ihre Jobs zur richtigen Zeit ausführt:

Kotlin

Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresStorageNotLow(true)
.setRequiresDeviceIdle(true)
.build()

Java

Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresStorageNotLow(true)
.setRequiresDeviceIdle(true)
.build()
  • Wenn du Jobs regelmäßig ausführen musst (z. B. um Als Nächstes ansehen basierend auf den Wiedergabeaktivitäten eines Nutzers in deiner App auf einem anderen Gerät zu aktualisieren), solltest du die Arbeitsspeichernutzung niedrig halten und die Arbeitsspeichernutzung des Jobs unter 30 MB halten.

Weitere allgemeine Richtlinien

Die folgenden Richtlinien enthalten allgemeine Informationen zur Entwicklung von Android-Apps:

  • Minimieren Sie die Objektzuweisungen, optimieren Sie die Wiederverwendung von Objekten und heben Sie die Zuweisung nicht verwendeter Objekte umgehend auf.
    • Behalten Sie keine Verweise auf Objekte, insbesondere auf Bitmaps.
    • Verwenden Sie System.gc() und direkte Aufrufe zum Freigeben von Arbeitsspeicher nicht, da sie die Speicherverwaltung des Systems beeinträchtigen. Beispielsweise kann ein erzwungener Aufruf von gc() auf Geräten mit zRAM die Speichernutzung vorübergehend erhöhen, da der Arbeitsspeicher komprimiert und dekomprimiert wird.
    • Verwenden Sie LazyList, wie in einem Katalogbrowser in Compose gezeigt, oder RecyclerView im jetzt eingestellten Leanback-UI-Toolkit, um Ansichten wiederzuverwenden und Listenelemente nicht neu zu erstellen.
    • Speichern Sie Elemente, die von externen Inhaltsanbietern gelesen werden und sich mit hoher Wahrscheinlichkeit nicht ändern, lokal im Cache und definieren Sie Aktualisierungsintervalle, die das Zuweisen zusätzlichen externen Arbeitsspeichers verhindern.
  • Prüfen Sie, ob es Speicherlecks gibt.
    • Achten Sie auf typische Speicherlecks wie Verweise in anonymen Threads, die Neuzuweisung von Video-Puffern, die nie freigegeben werden, und ähnliche Situationen.
    • Verwenden Sie einen Heap-Dump, um Speicherlecks zu beheben.
  • Erstellen Sie Baseline-Profile, um die Menge der Just-in-Time-Kompilierung zu minimieren, die beim Ausführen Ihrer App bei einem Kaltstart erforderlich ist.

Tools – Übersicht