Ab Android 3.0 (API-Level 11) unterstützt die 2D-Rendering-Pipeline von Android Hardware
Beschleunigung, d. h. alle Zeichenvorgänge, die auf einer
Das Canvas von View
verwendet die GPU. Aufgrund der erhöhten Ressourcen, die erforderlich sind,
Hardwarebeschleunigung erfordert, dass Ihre App mehr RAM benötigt.
Die Hardwarebeschleunigung ist standardmäßig aktiviert, wenn dein Ziel-API-Level >= 14 ist, kann aber auch
explizit aktiviert werden. Wenn Ihre Anwendung nur Standardansichten und
Für Drawable
s sollte bei globaler Aktivierung keine nachteilige Zeichnung verursacht werden.
Effekte. Da die Hardwarebeschleunigung jedoch nicht für alle 2D-Zeichnungen
kann sich die Aktivierung auf einige Ihrer benutzerdefinierten Ansichten oder Zeichenaufrufe auswirken. Probleme
äußern sich meist als unsichtbare Elemente, Ausnahmen oder falsch gerenderte Pixel. Bis
Abhilfe können Sie in Android die Hardwarebeschleunigung an mehreren
Niveau. Weitere Informationen finden Sie unter Hardwarebeschleunigung steuern.
Wenn Ihre Anwendung benutzerdefinierte Zeichnungen durchführt, testen Sie sie auf echten Hardwaregeräten. bei aktivierter Hardwarebeschleunigung, um Probleme zu finden. Im Abschnitt Unterstützung für Zeichenvorgänge werden bekannte Probleme mit Hardwarebeschleunigung und um diese zu umgehen.
Siehe auch OpenGL mit den Framework APIs und Renderscript
Hardwarebeschleunigung steuern
Sie können die Hardwarebeschleunigung auf den folgenden Ebenen steuern:
- Wissen anwenden
- Aktivität
- Fenster
- Ansehen
Anwendungsebene
Fügen Sie in Ihrer Android-Manifestdatei das folgende Attribut zum
<ph type="x-smartling-placeholder"></ph>
<application>
-Tag, um die Hardwarebeschleunigung für die gesamte
Anwendung:
<application android:hardwareAccelerated="true" ...>
Aktivitätslevel
Wenn sich Ihre Anwendung mit global aktivierter Hardwarebeschleunigung nicht ordnungsgemäß verhält,
auch für einzelne Aktivitäten steuern. Um die Hardwarebeschleunigung zu aktivieren oder zu deaktivieren,
Aktivitätsebene haben, können Sie das Attribut android:hardwareAccelerated
für
das
<activity>
-Element. Im folgenden Beispiel wird die Hardwarebeschleunigung für
die gesamte Anwendung, deaktiviert sie jedoch für eine Aktivität:
<application android:hardwareAccelerated="true"> <activity ... /> <activity android:hardwareAccelerated="false" /> </application>
Fensterebene
Wenn du eine noch genauere Steuerung benötigst, kannst du die Hardwarebeschleunigung für eine bestimmte Fenster mit dem folgenden Code:
Kotlin
window.setFlags( WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED )
Java
getWindow().setFlags( WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
Hinweis: Die Hardwarebeschleunigung kann derzeit nicht unter Fensterebene an.
Datenansichtsebene
Um die Hardwarebeschleunigung für eine einzelne Ansicht zur Laufzeit zu deaktivieren, verwenden Sie die folgenden Code:
Kotlin
myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null)
Java
myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
Hinweis: Sie können die Hardwarebeschleunigung derzeit nicht unter auf der Datenansichtsebene. Ansichtsebenen haben neben der Deaktivierung der Hardwarebeschleunigung noch weitere Funktionen. Weitere Informationen zu ihrer Verwendung finden Sie unter Ebenen ansehen.
Bestimmen, ob eine Ansicht hardwarebeschleunigt ist
Manchmal ist es hilfreich, wenn eine Anwendung weiß, ob es sich um Hardware handelt. insbesondere bei benutzerdefinierten Ansichten. Dies ist besonders nützlich, der Anwendung viele benutzerdefinierte Zeichnungen, und nicht alle Vorgänge werden vom neuen Rendering-Pipeline.
Es gibt zwei Möglichkeiten, um zu prüfen, ob eine Anwendung hardwarebeschleunigt ist:
View.isHardwareAccelerated()
Rückgaberechttrue
, wennView
mit einem hardwarebeschleunigten Gerät verbunden ist .Canvas.isHardwareAccelerated()
gibttrue
zurück, wennCanvas
hardwarebeschleunigt ist.
Wenn Sie dies in Ihrem Zeichencode tun müssen, verwenden Sie
Stattdessen Canvas.isHardwareAccelerated()
von View.isHardwareAccelerated()
. Wenn ein Aufruf
an einem hardwarebeschleunigten Fenster montiert ist, kann es dennoch mit anderen
beschleunigten Canvas. Dies geschieht z. B. beim Zeichnen einer Ansicht in eine Bitmap zur Speicherung im Cache.
zu verstehen.
Android-Zeichnungsmodelle
Wenn die Hardwarebeschleunigung aktiviert ist, nutzt das Android-Framework ein neues Zeichenmodell, nutzt Anzeigelisten, um Ihre App auf dem Bildschirm zu rendern. Um das Verständnis und wie sich diese auf Ihre Anwendung auswirken können, sollten Sie wissen, auch ohne Hardwarebeschleunigung. In den folgenden Abschnitten wird beschrieben, softwarebasierte und hardwarebeschleunigte Zeichenmodelle.
Softwarebasiertes Zeichenmodell
Im Software-Zeichenmodell werden Ansichten in den folgenden zwei Schritten gezeichnet:
- Hierarchie ungültig machen
- Hierarchie zeichnen
Wenn eine Anwendung einen Teil ihrer UI aktualisieren muss, wird invalidate()
(oder eine ihrer Varianten) für jede Ansicht aufgerufen, die sich geändert hat.
Inhalte. Die Entwertungsmeldungen werden zu Berechnungszwecken in der Ansichtshierarchie nach oben weitergegeben.
die Bereiche des Bildschirms, die neu gezeichnet werden müssen (der schmutzige Bereich). Das Android-System
zeichnet jede Ansicht in der Hierarchie, die sich mit dem schmutzigen Bereich überschneidet. Leider gibt es
Dieses Zeichnungsmodell hat zwei Nachteile:
- Erstens muss bei diesem Modell bei jedem Zeichendurchlauf viel Code ausgeführt werden. Wenn beispielsweise
Ihre Anwendung
invalidate()
für eine Schaltfläche aufruft und dass über einer anderen Ansicht befindet, zeichnet das Android-System die Ansicht neu, obwohl dies geändert. - Das zweite Problem besteht darin, dass das Zeichnungsmodell Programmfehler in Ihrer Anwendung verstecken kann. Da die
Das Android-System erstellt Ansichten neu, wenn sie sich mit der schmutzigen Region überschneiden, einer Ansicht, deren Inhalte du
geändert möglicherweise neu gezeichnet, obwohl
invalidate()
nicht gearbeitet hat. In diesem Fall verlassen Sie sich darauf, dass eine andere Ansicht für ungültig erklärt wird, um den für ein korrektes Verhalten. Dieses Verhalten kann sich jedes Mal ändern, wenn Sie Ihre Anwendung ändern. Aus sollten Sie immerinvalidate()
für Ihre benutzerdefinierte wenn Sie Daten oder Status ändern, die sich auf den Zeichencode der Ansicht auswirken.
Hinweis: Android-Ansichten rufen automatisch invalidate()
auf, wenn sich ihre Eigenschaften ändern, z. B. der Hintergrund.
Farbe oder den Text in TextView
.
Hardwarebeschleunigtes Zeichnenmodell
Das Android-System verwendet weiterhin invalidate()
und draw()
, um Bildschirmupdates anzufordern und Ansichten zu rendern, es verarbeitet aber
tatsächliche Zeichnung anders. Anstatt die Zeichenbefehle sofort auszuführen,
werden sie in Anzeigelisten aufgezeichnet, die die Ausgabe der
Code zu zeichnen. Eine weitere Optimierung besteht darin, dass das Android-System
Displaylisten für Ansichten, die von einem invalidate()
als als als schmutzig gekennzeichnet sind
aufrufen. Ansichten, die nicht ungültig gemacht wurden, können einfach durch erneutes Ausstellen des zuvor
der Display-Aufzeichnungen. Das neue Zeichnungsmodell umfasst drei Phasen:
- Hierarchie ungültig machen
- Displaylisten aufzeichnen und aktualisieren
- Anzeigelisten zeichnen
Bei diesem Modell können Sie sich nicht darauf verlassen, dass die Methode draw()
von einer Ansicht ausgeführt wird, die den schmutzigen Bereich überschneidet. Um sicherzustellen, dass das Android-System
angezeigt wird, müssen Sie invalidate()
aufrufen. Wird entfernt
führt dies dazu, dass eine Ansicht auch nach einer Änderung gleich aussieht.
Die Verwendung von Displaylisten
verbessert auch die Animationsleistung, da
wie Alpha- oder Rotationstechnik, muss die Ansicht mit der Ausrichtung nicht ungültig werden.
automatisch). Diese Optimierung gilt auch für Aufrufe mit Displaylisten, also für alle Aufrufe, die
Anwendung hardwarebeschleunigt ist.) Angenommen, es gibt eine LinearLayout
, die eine ListView
über Button
enthält. Die Anzeigeliste für LinearLayout
sieht wie folgt aus:
dies:
- DrawDisplayList(ListView)
- DrawDisplayList(Schaltfläche)
Angenommen, Sie möchten die Deckkraft von ListView
ändern. Nachher
Durch Aufrufen von setAlpha(0.5f)
für ListView
wird die Anzeigeliste nun
enthält Folgendes:
- SaveLayerAlpha(0.5)
- DrawDisplayList(ListView)
- Wiederherstellen
- DrawDisplayList(Schaltfläche)
Der komplexe Zeichencode von ListView
wurde nicht ausgeführt. Stattdessen
Das System hat lediglich die Anzeigeliste der wesentlich einfacheren LinearLayout
aktualisiert. In
bei einer Anwendung ohne aktivierte Hardwarebeschleunigung, den Zeichencode der Liste und der
Parent werden noch einmal ausgeführt.
Unterstützung für Zeichenvorgänge
Bei einer hardwarebeschleunigten 2D-Rendering-Pipeline unterstützt die 2D-Rendering-Pipeline die am häufigsten verwendeten
Canvas
-Zeichnungsvorgänge und viele weniger häufig verwendete Vorgänge. Alle
Zeichenoperationen, die zum Rendern von Android-Anwendungen verwendet werden, sind Standard-Widgets
Layouts und gängige erweiterte visuelle Effekte wie Reflexionen und gekachelte Texturen
unterstützt.
In der folgenden Tabelle wird die Unterstützungsstufe für verschiedene Vorgänge auf allen API-Ebenen beschrieben:
Erstes unterstütztes API-Level | ||||
Canvas | ||||
drawBitmapMesh() (Farbarray) | 18 | |||
drawPicture() | 23 | |||
drawPosText() | 16 | |||
drawTextOnPath() | 16 | |||
drawVertices() | 29 | |||
setDrawFilter() | 16 | |||
ClipPath() | 18 | |||
ClipRegion() | 18 | |||
ClipRect(Region.Op.XOR) | 18 | |||
ClipRect(Region.Op.Differenz) | 18 | |||
ClipRect(Region.Op.ReverseDifference) | 18 | |||
ClipRect() mit Drehung/Perspektive | 18 | |||
Farbe | ||||
setAntiAlias() (für Text) | 18 | |||
setAntiAlias() (für Zeilen) | 16 | |||
setFilterBitmap() | 17 | |||
setLinearText() | ✗ | |||
setMaskFilter() | ✗ | |||
setPathEffect() (für Linien) | 28 | |||
setShadowLayer() (außer Text) | 28 | |||
setStrokeCap() (für Linien) | 18 | |||
setStrokeCap() (für Punkte) | 19 | |||
setSubpixelText() | 28 | |||
Xfer-Modus | ||||
PorterDuff.Mode.DARKEN (Framebuffer) | 28 | |||
PorterDuff.Mode.LIGHTEN (Framebuffer) | 28 | |||
PorterDuff.Mode.OVERLAY (Framebuffer) | 28 | |||
Shader | ||||
ComposeShader in ComposeShader | 28 | |||
Gleiche Shader in ComposeShader | 28 | |||
Lokale Matrix in ComposeShader | 18 |
Canvas-Skalierung
Die hardwarebeschleunigte 2D-Rendering-Pipeline wurde zuerst entwickelt, um das Zeichnen ohne Skalierung zu unterstützen, wobei einige Zeichenvorgänge bei höheren Skalenwerten die Qualität erheblich verschlechtern. Diese Operationen werden als Texturen implementiert, die im Maßstab 1.0 gezeichnet und von der GPU transformiert werden. In API starten Ebene 28 können alle Zeichenvorgänge problemlos skaliert werden.
In der folgenden Tabelle sehen Sie, wann die Implementierung geändert wurde, damit große Datenmengen korrekt verarbeitet werden können:Zu skalierender Zeichnungsvorgang | Erstes unterstütztes API-Level |
drawText() | 18 |
drawPosText() | 28 |
drawTextOnPath() | 28 |
Einfache Formen* | 17 |
Komplexe Formen* | 28 |
DrawPath(): | 28 |
Schattenebene | 28 |
Hinweis: „Einfach“ Formen sind drawRect()
,
drawCircle()
, drawOval()
, drawRoundRect()
und
drawArc()
-Befehle (mit useCenter=false) für Paint ohne
PathEffect und enthält keine nicht standardmäßigen Joins (über setStrokeJoin()
/
setStrokeMiter()
. Andere Instanzen dieser Zeichenbefehle fallen
unter "Komplex", in
im obigen Diagramm.
Wenn Ihre App von einer dieser fehlenden Funktionen oder Einschränkungen betroffen ist, können Sie
deaktivieren Sie die Hardwarebeschleunigung nur für den betroffenen Teil Ihrer Anwendung, indem Sie den Aufruf
setLayerType(View.LAYER_TYPE_SOFTWARE, null)
Auf diese Weise können Sie
und überall sonst die Hardwarebeschleunigung nutzen. Weitere Informationen zum Aktivieren der Funktion findest du unter Hardwarebeschleunigung steuern.
und deaktivieren Sie die Hardwarebeschleunigung
auf verschiedenen Stufen in Ihrer Anwendung.
Ebenen ansehen
In allen Android-Versionen konnten
Aufrufe in Zwischenspeicher außerhalb des Bildschirms
entweder mithilfe des Zeichencaches einer Ansicht oder mithilfe von Canvas.saveLayer()
. Für Zwischenspeicher außerhalb des Bildschirms oder Ebenen gibt es mehrere Verwendungszwecke. Sie können sie nutzen,
bessere Leistung bei der Animation komplexer Ansichten oder beim Anwenden von Kompositionseffekten Beispiel:
Sie können Ausblendungseffekte mit Canvas.saveLayer()
implementieren, um eine Ansicht vorübergehend zu rendern
in eine Ebene umwandeln und anschließend
mit einem Deckkraftfaktor wieder auf dem Bildschirm darstellen.
Ab Android 3.0 (API-Level 11) haben Sie mehr Kontrolle darüber, wie und wann Sie Ebenen verwenden.
mit der Methode View.setLayerType()
. Diese API verwendet zwei
Parameter: der Ebenentyp, den Sie verwenden möchten, und ein optionales Paint
-Objekt, das beschreibt, wie die Ebene zusammengesetzt werden soll. Mit dem Parameter Paint
können Sie Farbfilter, spezielle Mischmodi oder die Deckkraft auf ein Element anwenden.
Ebene. Für Ansichten kann einer von drei Ebenentypen verwendet werden:
LAYER_TYPE_NONE
: Die Ansicht wird normal gerendert und nicht gesichert. durch einen Zwischenspeicher außerhalb des Bildschirms gesprochen. Dies ist die Standardeinstellung.LAYER_TYPE_HARDWARE
: Die Ansicht wird Hardware in einen Hardware-Textur, wenn die Anwendung hardwarebeschleunigt ist. Wenn die Anwendung keine Hardware ist beschleunigt wird, verhält sich dieser Ebenentyp genauso wieLAYER_TYPE_SOFTWARE
.LAYER_TYPE_SOFTWARE
: Die Ansicht wird in Software in ein Bitmap.
Welche Art von Ebene Sie verwenden, hängt von Ihrem Ziel ab:
- Leistung: Verwenden Sie einen Hardwareebenentyp, um eine Ansicht in eine Hardware zu rendern.
Textur. Sobald eine Ansicht in einer Ebene gerendert wurde, muss ihr Zeichencode nicht mehr ausgeführt werden
bis die Ansicht
invalidate()
aufruft. Einige Animationen, wie z. B. Alpha-Animationen können anschließend direkt auf die Ebene angewendet werden, die die GPU erledigen soll. - Visuelle Effekte: Verwenden Sie einen Hardware- oder Softwareebenentyp und einen
Paint
, um eine Ansicht mit besonderen visuellen Effekten zu versehen. Zum Beispiel können Sie Zeichnen Sie eine schwarz-weiße Ansicht mitColorMatrixColorFilter
. - Kompatibilität: Verwenden Sie einen Softwareebenentyp, um das Rendern einer Ansicht zu erzwingen. Software. Wenn eine hardwarebeschleunigte Ansicht (z. B. wenn Ihr gesamter Hardwarebeschleunigung), Rendering-Probleme haben, ist dies eine einfache Möglichkeit, zu Einschränkungen des Hardware-Renderings zu erstellen.
Ebenen und Animationen ansehen
Hardwareebenen können schnellere und flüssigere Animationen liefern, wenn Ihre Anwendung
ist hardwarebeschleunigt. Eine Animation mit 60 Bildern pro Sekunde ist nicht immer möglich,
Animieren komplexer Ansichten,
die viele Zeichenvorgänge ausführen. Dies lässt sich beheben, indem
mit Hardwareebenen, um die Ansicht als Hardware-Textur zu rendern. Die Hardware-Textur kann
dann zum Animieren der Ansicht verwendet werden, sodass die Ansicht sich nicht ständig neu zeichnen muss.
wenn es animiert ist. Die Ansicht wird erst dann neu gezeichnet, wenn Sie die
Eigenschaften, die invalidate()
aufrufen, oder wenn Sie invalidate()
manuell aufrufen. Wenn Sie eine Animation in
und erzielen nicht die gewünschten flüssigen Ergebnisse, sollten Sie erwägen, Hardwareschichten auf
Ihre animierten Ansichten.
Wenn eine Ansicht von einer Hardwareschicht gestützt wird, werden einige ihrer Eigenschaften über die Art und Weise verarbeitet, ist auf dem Bildschirm aufgebaut. Das Festlegen dieser Eigenschaften ist effizient, da sie die Ansicht ungültig gemacht und neu gezeichnet werden. Die folgende Liste von Properties beeinflusst, aus der Schicht besteht. Das Aufrufen des Setters für eine dieser Eigenschaften führt zu optimalen Entwertung und kein erneutes Zeichnen der Zielansicht:
alpha
: ändert die Deckkraft der Ebene.x
,y
,translationX
,translationY
: Ändert die Position der EbenescaleX
,scaleY
: Ändert die Größe der Ebene.rotation
,rotationX
,rotationY
: Ändert die Ausrichtung der Ebene im 3D-RaumpivotX
,pivotY
: Ändert den Ursprung der Transformationen der Ebene.
Diese Eigenschaften sind die Namen, die beim Animieren einer Ansicht mit einem ObjectAnimator
verwendet werden. Wenn Sie auf diese Eigenschaften zugreifen möchten, rufen Sie die entsprechende
Setter oder Getter. Wenn Sie beispielsweise das Attribut „Alpha“ ändern möchten, rufen Sie setAlpha()
auf. Das folgende Code-Snippet zeigt die effizienteste Methode,
, um ein 3D-Ansicht um die Y-Achse zu drehen:
Kotlin
view.setLayerType(View.LAYER_TYPE_HARDWARE, null) ObjectAnimator.ofFloat(view, "rotationY", 180f).start()
Java
view.setLayerType(View.LAYER_TYPE_HARDWARE, null); ObjectAnimator.ofFloat(view, "rotationY", 180).start();
Da Hardwareebenen den Videospeicher verbrauchen, wird dringend empfohlen, sie zu aktivieren. nur für die Dauer der Animation und deaktivieren sie nach Abschluss der Animation. Ich erreichen Sie dies mithilfe von Animations-Listenern:
Kotlin
view.setLayerType(View.LAYER_TYPE_HARDWARE, null) ObjectAnimator.ofFloat(view, "rotationY", 180f).apply { addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { view.setLayerType(View.LAYER_TYPE_NONE, null) } }) start() }
Java
view.setLayerType(View.LAYER_TYPE_HARDWARE, null); ObjectAnimator animator = ObjectAnimator.ofFloat(view, "rotationY", 180); animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { view.setLayerType(View.LAYER_TYPE_NONE, null); } }); animator.start();
Weitere Informationen zur Property-Animation finden Sie unter Property-Animation.
Tipps und Tricks
Ein Wechsel zu hardwarebeschleunigter 2D-Grafik kann die Leistung sofort steigern, aber ihr Ihre Anwendung dennoch für eine effektive Nutzung der GPU entwickeln. Empfehlungen:
- Anzahl der Aufrufe in Ihrer Anwendung reduzieren
- Je mehr Ansichten das System erstellen muss, desto langsamer wird es. Dies gilt für die Software, Rendering-Pipeline aus. Das Reduzieren der Aufrufe ist eine der einfachsten Möglichkeiten, deine Benutzeroberfläche zu optimieren.
- Überzeichnung vermeiden
- Zeichnen Sie nicht zu viele Ebenen übereinander. Entfernen Sie alle Datenansichten, die vollständig oder durch andere dunkle Ansichten verdeckt wird. Wenn Sie mehrere Ebenen übereinander sollten Sie sie in einer Ebene zusammenführen. Eine gute Faustregel im Hinblick auf die aktuelle darf nicht mehr als das 2,5-fache der Pixelanzahl auf dem Bildschirm pro Frame gezeichnet werden. (transparente Pixel in einer Bitmap-Zählung!).
- Keine Renderingobjekte in Zeichenmethoden erstellen
- Ein häufiger Fehler besteht darin, bei jedem Aufruf einer Renderingmethode ein neues
Paint
- oderPath
-Objekt zu erstellen. Dadurch wird der Speicher Collector kann häufiger ausgeführt werden. Außerdem werden Caches und Optimierungen in der Hardware umgangen. zu erstellen. - Formen nicht zu oft ändern
- Komplexe Formen, Pfade und Kreise werden beispielsweise mithilfe von Texturmasken gerendert. Jeden erstellt oder geändert, erstellt die Hardwarepipeline eine neue Maske, die teuer sein.
- Bitmaps nicht zu oft ändern
- Jedes Mal, wenn Sie den Inhalt einer Bitmap ändern, wird sie wieder als GPU-Textur hochgeladen. wenn Sie es das nächste Mal zeichnen.
- Alphaversion mit Vorsicht verwenden
- Wenn Sie mit
setAlpha()
eine durchsichtige Ansicht erstellen,AlphaAnimation
oderObjectAnimator
in einem Zwischenspeicher außerhalb des Bildschirms gerendert, wodurch sich die erforderliche Ausführungsrate verdoppelt. Bei Anwendung von Alpha-Funktionen sehr großen Ansichten verwenden, können Sie den Ebenentyp der Ansicht aufLAYER_TYPE_HARDWARE