Auf dieser Seite erhalten Sie einen allgemeinen Überblick über die Architekturschichten von Jetpack Compose und die wichtigsten Prinzipien, die diesem Design zugrunde liegen.
Jetpack Compose ist kein einzelnes monolithisches Projekt, sondern besteht aus einer Reihe von Modulen, die zusammen einen vollständigen Stack bilden. Wenn Sie die verschiedenen Module von Jetpack Compose kennen, können Sie:
- Geeignete Abstraktionsebene für die Entwicklung Ihrer App oder Bibliothek verwenden
- Wissen, wann Sie für mehr Kontrolle oder Anpassungsmöglichkeiten auf eine niedrigere Ebene wechseln können
- Abhängigkeiten minimieren
Ebenen
Die wichtigsten Ebenen von Jetpack Compose sind:
Abbildung 1: Die wichtigsten Ebenen von Jetpack Compose.
Jede Ebene baut auf den unteren Ebenen auf und kombiniert Funktionen, um Komponenten auf höherer Ebene zu erstellen. Jede Ebene baut auf öffentlichen APIs der unteren Ebenen auf, um die Modulgrenzen zu überprüfen und es Ihnen zu ermöglichen, jede Ebene bei Bedarf zu ersetzen. Sehen wir uns diese Ebenen von unten nach oben an.
- Laufzeit
- Dieses Modul bietet die Grundlagen der Compose-Laufzeit, z. B.
remember
,mutableStateOf
, die Annotation@Composable
undSideEffect
. Sie können direkt auf dieser Ebene aufbauen, wenn Sie nur die Funktionen von Compose zur Baumverwaltung und nicht die Benutzeroberfläche benötigen. - Benutzeroberfläche
- Die UI-Ebene besteht aus mehreren Modulen (
ui-text
,ui-graphics
,ui-tooling
usw.). Diese Module implementieren die Grundlagen des UI-Toolkits, z. B.LayoutNode
,Modifier
, Eingabehandler, benutzerdefinierte Layouts und das Zeichnen. Sie sollten diese Ebene in Betracht ziehen, wenn Sie nur grundlegende Konzepte eines UI-Toolkits benötigen. - Grundlage
- Dieses Modul bietet designsystemunabhängige Bausteine für Compose UI, z. B.
Row
undColumn
,LazyColumn
, Erkennung bestimmter Gesten usw. Sie können auf der Fundierungsebene aufbauen, um Ihr eigenes Designsystem zu erstellen. - Material
- Dieses Modul bietet eine Implementierung des Material Design-Systems für Compose UI mit einem Theming-System, formatierten Komponenten, Ripple-Indikatoren und Symbolen. Diese Ebene ist die Grundlage für die Verwendung von Material Design in Ihrer App.
Designprinzipien
Ein Leitprinzip für Jetpack Compose ist es, kleine, fokussierte Funktionseinheiten bereitzustellen, die zusammengesetzt (oder komponiert) werden können, anstatt weniger monolithischer Komponenten. Dieser Ansatz bietet eine Reihe von Vorteilen.
Umfassende Kontrolle
Komponenten auf höherer Ebene bieten in der Regel mehr Funktionen, schränken aber die direkte Kontrolle ein. Wenn Sie mehr Kontrolle benötigen, können Sie eine Komponente auf niedrigerer Ebene verwenden.
Wenn Sie beispielsweise die Farbe einer Komponente animieren möchten, können Sie die animateColorAsState
API verwenden:
val color = animateColorAsState(if (condition) Color.Green else Color.Red)
Wenn die Komponente jedoch immer grau sein soll, ist das mit dieser API nicht möglich. Stattdessen können Sie die Animatable
API auf niedrigerer Ebene verwenden:
val color = remember { Animatable(Color.Gray) } LaunchedEffect(condition) { color.animateTo(if (condition) Color.Green else Color.Red) }
Die animateColorAsState
-API auf höherer Ebene basiert auf der Animatable
-API auf niedrigerer Ebene. Die Verwendung der API auf niedrigerer Ebene ist komplexer, bietet aber mehr Kontrolle. Wählen Sie die Abstraktionsebene aus, die Ihren Anforderungen am besten entspricht.
Personalisierung
Wenn Sie Komponenten höherer Ebene aus kleineren Bausteinen zusammensetzen, ist es viel einfacher, sie bei Bedarf anzupassen. Sehen Sie sich beispielsweise die Implementierung von Button
an, die von der Material-Ebene bereitgestellt wird:
@Composable fun Button( // … content: @Composable RowScope.() -> Unit ) { Surface(/* … */) { CompositionLocalProvider(/* … */) { // set LocalContentAlpha ProvideTextStyle(MaterialTheme.typography.button) { Row( // … content = content ) } } } }
Ein Button
besteht aus vier Komponenten:
Ein Material
Surface
für den Hintergrund, die Form, die Klickbehandlung usw.A
CompositionLocalProvider
damit sich der Alphawert des Inhalts ändert, wenn die Schaltfläche aktiviert oder deaktiviert wirdMit A
ProvideTextStyle
wird der zu verwendende Standardtextstil festgelegt.Eine
Row
stellt die Standardrichtlinie für das Layout des Inhalts der Schaltfläche bereit.
Wir haben einige Parameter und Kommentare weggelassen, um die Struktur zu verdeutlichen. Die gesamte Komponente umfasst jedoch nur etwa 40 Codezeilen, da sie lediglich diese vier Komponenten zusammenfügt, um die Schaltfläche zu implementieren. Bei Komponenten wie Button
wird festgelegt, welche Parameter verfügbar sind. Dabei wird ein Gleichgewicht zwischen der Möglichkeit, häufige Anpassungen vorzunehmen, und einer Vielzahl von Parametern geschaffen, die die Verwendung einer Komponente erschweren können. Material-Komponenten bieten beispielsweise Anpassungen, die im Material Design-System angegeben sind. So lassen sich die Material Design-Grundsätze leicht einhalten.
Wenn Sie jedoch eine Anpassung vornehmen möchten, die über die Parameter einer Komponente hinausgeht, können Sie eine Ebene tiefer gehen und eine Komponente forken. In Material Design wird beispielsweise festgelegt, dass Schaltflächen einen einfarbigen Hintergrund haben sollten. Wenn Sie einen Hintergrund mit Farbverlauf benötigen, wird diese Option von den Button
-Parametern nicht unterstützt. In diesem Fall können Sie die Material-Implementierung Button
als Referenz verwenden und Ihre eigene Komponente erstellen:
@Composable fun GradientButton( // … background: List<Color>, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit ) { Row( // … modifier = modifier .clickable(onClick = {}) .background( Brush.horizontalGradient(background) ) ) { CompositionLocalProvider(/* … */) { // set material LocalContentAlpha ProvideTextStyle(MaterialTheme.typography.button) { content() } } } }
Bei der oben genannten Implementierung werden weiterhin Komponenten aus der Material-Ebene verwendet, z. B. die Material-Konzepte für current content alpha (Alpha des aktuellen Inhalts) und den aktuellen Textstil. Dabei wird das Material Surface
durch ein Row
ersetzt und so formatiert, dass das gewünschte Aussehen erzielt wird.
Wenn Sie Material-Konzepte überhaupt nicht verwenden möchten, z. B. wenn Sie Ihr eigenes benutzerdefiniertes Designsystem erstellen, können Sie nur Komponenten der Fundierungsebene verwenden:
@Composable fun BespokeButton( // … backgroundColor: Color, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit ) { Row( // … modifier = modifier .clickable(onClick = {}) .background(backgroundColor) ) { // No Material components used content() } }
In Jetpack Compose sind die einfachsten Namen für die Komponenten der obersten Ebene reserviert. Beispiel: androidx.compose.material.Text
basiert auf androidx.compose.foundation.text.BasicText
.
So können Sie Ihrer eigenen Implementierung den am besten auffindbaren Namen geben, wenn Sie höhere Ebenen ersetzen möchten.
Die richtige Abstraktion auswählen
Die Philosophie von Compose, geschichtete, wiederverwendbare Komponenten zu erstellen, bedeutet, dass Sie nicht immer auf die untergeordneten Bausteine zurückgreifen sollten. Viele Komponenten der höheren Ebene bieten nicht nur mehr Funktionen, sondern implementieren oft auch Best Practices wie die Unterstützung der Barrierefreiheit.
Wenn Sie beispielsweise Ihrer benutzerdefinierten Komponente Unterstützung für Gesten hinzufügen möchten, können Sie diese Funktion mit Modifier.pointerInput
von Grund auf neu erstellen. Es gibt jedoch andere Komponenten auf höherer Ebene, die darauf aufbauen und einen besseren Ausgangspunkt bieten, z. B. Modifier.draggable
, Modifier.scrollable
oder Modifier.swipeable
.
In der Regel sollten Sie die Komponente der höchsten Ebene verwenden, die die benötigte Funktionalität bietet, um von den darin enthaltenen Best Practices zu profitieren.
Weitere Informationen
Ein Beispiel für das Erstellen eines benutzerdefinierten Designsystems finden Sie im Jetsnack-Beispiel.
Empfehlungen für dich
- Hinweis: Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Kotlin für Jetpack Compose
- Listen und Tabellen
- Nebeneffekte in Compose