Auf dieser Seite erhalten Sie einen allgemeinen Überblick über die Architekturebenen von Jetpack Compose und die grundlegenden Prinzipien, die diesem Design zugrunde liegen.
Jetpack Compose ist kein monolithisches Projekt, sondern besteht aus einer Reihe von Modulen, die zu einem vollständigen Stack zusammengesetzt werden. Wenn Sie die verschiedenen Module von Jetpack Compose kennen, haben Sie folgende Möglichkeiten:
- Die richtige Abstraktionsebene für die Entwicklung Ihrer App oder Bibliothek verwenden
- Informationen dazu, wann Sie zu einer niedrigeren Ebene wechseln können, um mehr Kontrolle oder Anpassungsmöglichkeiten zu erhalten
- Abhängigkeiten minimieren
Ebenen
Die wichtigsten Schichten von Jetpack Compose sind:
Abbildung 1. Die Hauptschichten von Jetpack Compose.
Jede Schicht baut auf den darunter liegenden Schichten auf und kombiniert Funktionen, um Komponenten höherer Ebene zu erstellen. Jede Ebene baut auf öffentlichen APIs der darunter liegenden Ebenen auf, um die Modulgrenzen zu überprüfen und Sie bei Bedarf in die Lage zu versetzen, eine Ebene zu ersetzen. Sehen wir uns diese Schichten von unten nach oben an.
- Laufzeit
- In diesem Modul werden die Grundlagen der Compose-Laufzeit erläutert, z. B.
remember
,mutableStateOf
, die Anmerkung@Composable
undSideEffect
. Sie können diese Ebene direkt verwenden, wenn Sie nur die Baumverwaltungsfunktionen von Compose und nicht die Benutzeroberfläche benötigen. - Benutzeroberfläche
- Die UI-Ebene besteht aus mehreren Modulen ( z. B.
ui-text
,ui-graphics
undui-tooling
). Diese Module implementieren die Grundlagen des UI-Toolkits, z. B.LayoutNode
,Modifier
, Eingabehandler, benutzerdefinierte Layouts und Zeichnen. Sie können diese Ebene verwenden, wenn Sie nur die grundlegenden Konzepte eines UI-Toolkits benötigen. - Grundlagen
- Dieses Modul bietet designsystemunabhängige Bausteine für die Compose-Benutzeroberfläche, z. B.
Row
undColumn
,LazyColumn
und die Erkennung bestimmter Touch-Gesten. Sie können die Basisschicht als Ausgangspunkt für Ihr eigenes Designsystem verwenden. - Material
- Dieses Modul bietet eine Implementierung des Material Design-Systems für die Compose-Benutzeroberfläche, einschließlich eines Designsystems, stilisierter Komponenten, Ripple-Anzeige und Symbole. Wenn Sie Material Design in Ihrer App verwenden, bauen Sie auf dieser Ebene auf.
Designprinzipien
Ein Leitprinzip für Jetpack Compose besteht darin, kleine, fokussierte Funktionen bereitzustellen, die zusammengesetzt (oder komponiert) werden können, anstatt nur wenige monolithische Komponenten. Dieser Ansatz bietet eine Reihe von Vorteilen.
Umfassende Kontrolle
Komponenten auf höherer Ebene bieten in der Regel mehr Funktionen, beschränken aber Ihre direkte Kontrolle. Wenn Sie mehr Kontrolle benötigen, können Sie eine Komponente einer niedrigeren 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 API der unteren Ebene Animatable
verwenden:
val color = remember { Animatable(Color.Gray) } LaunchedEffect(condition) { color.animateTo(if (condition) Color.Green else Color.Red) }
Die animateColorAsState
API der höheren Ebene basiert selbst auf der Animatable
API der niedrigeren Ebene. Die Verwendung der API der unteren 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 zusammenstellen, lassen sich die Komponenten bei Bedarf viel einfacher anpassen. Betrachten wir beispielsweise die Implementierung von Button
, die von der Materialebene 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, das den Hintergrund, die Form, die Klickbehandlung usw. bereitstellt
Surface
Ein
CompositionLocalProvider
, mit dem sich das Alpha des Inhalts ändert, wenn die Schaltfläche aktiviert oder deaktiviert istMit einem
ProvideTextStyle
wird der zu verwendende Standardtextstil festgelegt.Eine
Row
gibt die Standardlayoutrichtlinie für den Inhalt der Schaltfläche an.
Wir haben einige Parameter und Kommentare weggelassen, um die Struktur klarer zu machen. Die gesamte Komponente besteht jedoch nur aus etwa 40 Codezeilen, da sie einfach diese vier Komponenten zur Implementierung der Schaltfläche zusammensetzt. Bei Komponenten wie Button
ist es wichtig, welche Parameter freigegeben werden. Dabei wird ein Gleichgewicht zwischen gängigen Anpassungen und einer Explosion von Parametern geschaffen, die die Verwendung einer Komponente erschweren können. Material-Komponenten bieten beispielsweise Anpassungen, die im Material Design-System festgelegt sind, sodass die Material Design-Prinzipien leicht eingehalten werden können.
Wenn Sie jedoch eine Anpassung über die Parameter einer Komponente hinaus vornehmen möchten, können Sie eine Ebene nach unten wechseln und eine Komponente forken. Beispielsweise legt Material Design fest, dass Schaltflächen einen einfarbigen Hintergrund haben sollten. Wenn Sie einen Farbverlauf als Hintergrund benötigen, wird diese Option von den Button
-Parametern nicht unterstützt. In diesem Fall können Sie die Material Button
-Implementierung 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() } } } }
In der obigen Implementierung werden weiterhin Komponenten aus der Material-Ebene verwendet, z. B. die Material-Konzepte aktueller Inhalts-Alphawert und der aktuelle Textstil. Es ersetzt jedoch das Material Surface
durch ein Row
und gestaltet es so, dass das gewünschte Erscheinungsbild erreicht wird.
Wenn Sie keine Material-Konzepte verwenden möchten, z. B. wenn Sie Ihr eigenes Designsystem erstellen, können Sie nur Komponenten der Basisschicht 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
Da Compose darauf ausgelegt ist, mehrschichtige, wiederverwendbare Komponenten zu erstellen, sollten Sie nicht immer die Bausteine der unteren Ebene verwenden. Viele Komponenten der höheren Ebene bieten nicht nur mehr Funktionen, sondern implementieren oft Best Practices wie die Unterstützung der Barrierefreiheit.
Wenn Sie Ihrer benutzerdefinierten Komponente beispielsweise Gestenunterstützung hinzufügen möchten, können Sie diese 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
.
Als Faustregel gilt: Bauen Sie vorzugsweise auf der Komponente der höchsten Ebene auf, die die benötigte Funktionalität bietet, um von den Best Practices zu profitieren, die sie enthalten.
Weitere Informationen
Im Beispiel für Jetsnack finden Sie ein Beispiel für die Erstellung eines benutzerdefinierten Designsystems.
Empfehlungen für dich
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Kotlin für Jetpack Compose
- Listen und Raster
- Nebeneffekte in Compose