@Composable: was es ist, Compose-Annotation und Anwendungsbereich

Autor: IT Sectr Veröffentlicht: 2026-06-27 Lesezeit: 8 Min.

Die @Composable-Annotation ist ein grundlegendes Element von Jetpack Compose, das eine gewöhnliche Kotlin-Funktion in einen deklarativen Baustein der Benutzeroberfläche verwandelt. Ohne diese Annotation ist es unmöglich, einen Bildschirm in der modernen Android-Entwicklung zu erstellen. Laut Google Android Developers, 2026 verwenden mehr als 80% der neuen Kotlin-Projekte Compose für die UI-Erstellung, und @Composable ist die am häufigsten verwendete Annotation im Ökosystem.

Wichtige Punkte

  • @Composable — eine Kotlin-Annotation, die einer Funktion ermöglicht, UI deklarativ zu beschreiben
  • Composable-Funktionen können nur andere Composable-Funktionen aufrufen, unter Beachtung des Kompositionskontexts
  • Neustart von Composable-Funktionen erfolgt bei Änderung der Eingabeparameter oder des Zustands
  • Aufrufreihenfolge von Composable-Funktionen ist nicht garantiert — Compose optimiert den UI-Wiederaufbau
  • Benennung von Composable-Funktionen folgt der PascalCase-Konvention, wie alle Komponenten in Compose

Was ist @Composable in Jetpack Compose

@Composable ist eine Annotation der Sprache Kotlin, die eine Funktion als für die Beschreibung der Benutzeroberfläche im Jetpack Compose-Framework markiert. Wenn der Kotlin-Compiler diese Annotation findet, generiert er zusätzlichen Code, der es der Funktion ermöglicht, im Kompositionskontext — dem UI-Baum-Verwaltungssystem — zu arbeiten.

Die @Composable-Annotation wurde von Google im Jahr 2021 zusammen mit der ersten stabilen Version von Jetpack Compose 1.0 eingeführt. Vor ihrem Erscheinen erfolgte die Android-Schnittstellenentwicklung ausschließlich über XML-Markup und das View-System. @Composable hat den Ansatz grundlegend verändert: Anstatt die UI in einer separaten Markup-Datei zu beschreiben, schreibt der Entwickler die Oberfläche direkt in Kotlin.

Der Hauptunterschied zwischen @Composable und gewöhnlichen Kotlin-Funktionen ist die Fähigkeit, Zustand zu lesen und auf Änderungen zu reagieren. Wenn eine Variable, die eine Composable-Funktion liest, ihren Wert ändert, plant das System automatisch einen Neustart (Neuzusammensetzung) dieser Funktion. Dies befreit den Entwickler vom manuellen Aktualisieren der UI über findViewById und setText.

Die interne Mechanik von @Composable basiert auf dem Slot-Konzept — einem speziellen Speicherbereich, der für jede Funktion innerhalb der Komposition reserviert wird. Dieser Slot speichert die an die Funktion übergebenen Werte sowie die Dienstinformationen, die für den Vergleich bei nachfolgenden Aufrufen erforderlich sind.

Wie deklariert man eine Composable-Funktion

Um eine Composable-Funktion zu deklarieren, fügt man einfach die @Composable-Annotation vor dem Schlüsselwort fun hinzu. Die Funktion muss sich in einem Paket befinden, das die Annotation aus androidx.compose.runtime importiert. Es wird empfohlen, den Funktionsnamen mit einem Großbuchstaben zu beginnen — dies ist eine weit verbreitete Konvention in der Compose-Community, die UI-Komponenten visuell von gewöhnlichen Funktionen unterscheidet.

kotlin
import androidx.compose.runtime.Composable

@Composable
fun Greeting(name: String) {
    var count by remember { mutableStateOf(0) }
    Column {
        Text("Hallo, $name!")
        Button(onClick = { count++ }) {
            Text("$count Mal geklickt")
        }
    }
}

Die Parameter einer Composable-Funktion können beliebig sein — primitive Typen, Zeichenketten, Lambdas und sogar andere Composable-Funktionen, die über die Slot-API übergeben werden. Empfohlen wird, Parameter unveränderlich (val) zu machen, um Nebeneffekte während der Neuzusammensetzung zu vermeiden. Alle veränderlichen Daten sollten über die Zustandsmechanismen von Compose verwaltet werden.

Composable-Funktionen können keine beliebigen Werte wie reguläre Funktionen zurückgeben — ihre einzige Aufgabe ist es, einen Teil des UI-Baums zu erstellen oder zu aktualisieren. Es gibt jedoch spezielle Muster wie State Hoisting, bei dem eine Compose-Funktion Zustand und Callbacks über Parameter annimmt und dabei rein und wiederverwendbar bleibt.

Regeln für Composable-Funktionen in Kotlin

Das Compose-System legt mehrere strenge Einschränkungen fest, wie Composable-Funktionen aussehen und sich verhalten sollen. Die erste Regel: Eine Composable-Funktion darf nur andere Composable-Funktionen oder reguläre Funktionen ohne Nebeneffekte aufrufen. Dies gewährleistet die Vorhersagbarkeit der Komposition und die korrekte Funktionsweise der Compose-Optimierungen.

Die zweite Regel betrifft die Ausführungsreihenfolge. Compose hat das Recht, Composable-Funktionen in beliebiger Reihenfolge aufzurufen, daher darf der Code im Körper einer solchen Funktion nicht von der Aufrufsequenz benachbarter Funktionen abhängen. Jede Composable-Funktion muss auf der Ebene ihrer Position im UI-Baum autark sein.

Die dritte Regel — Verbot von Nebeneffekten innerhalb des Körpers einer Composable-Funktion. Operationen wie Datenbankzugriffe, Netzwerkanfragen oder das Ändern externer Variablen dürfen nur innerhalb spezieller Effekte ausgeführt werden: LaunchedEffect, DisposableEffect oder SideEffect. Ein Verstoß gegen diese Regel führt zu unvorhersehbarem Verhalten bei Neuzusammensetzungen.

Die vierte Regel: Composable-Funktionen müssen idempotent sein. Ein erneuter Aufruf mit denselben Argumenten sollte dieselbe UI erzeugen. Diese Anforderung ist für die korrekte Funktionsweise der Skipping-Optimierung notwendig, bei der Compose das Neuzeichnen von Funktionen überspringt, deren Eingabedaten sich nicht geändert haben.

kotlin
// Richtig: reine Composable-Funktion ohne Nebeneffekte
@Composable
fun UserCard(user: User, onClick: () -> Unit) {
    Card(modifier = Modifier.clickable { onClick() }) {
        Text(text = user.name)
    }
}

// Falsch: Nebeneffekt innerhalb des Körpers
@Composable
fun WrongCard(userId: String) {
    // val result = viewModel.loadUser(userId)  // NICHT ERLAUBT
    Text("Lädt...")
}

Beispiele für die Verwendung von @Composable

Betrachten wir ein praktisches Beispiel für die Erstellung eines Profilbildschirms mit der @Composable-Annotation. Hier zeigen wir die Kombination mehrerer Composable-Funktionen, die Arbeit mit Zustand und Modifikatoren — Schlüsselelemente jedes Compose-Layouts.

kotlin
@Composable
fun ProfileScreen(userId: String) {
    var isFollowed by remember { mutableStateOf(false) }

    Column(modifier = Modifier.fillMaxSize().padding(16.dp)) {
        ProfileHeader(userId = userId)
        Spacer(modifier = Modifier.height(16.dp))
        StatsRow(posts = 42, followers = 1280)
        Spacer(modifier = Modifier.height(24.dp))
        FollowButton(
            isFollowed = isFollowed,
            onToggle = { isFollowed = !isFollowed }
        )
    }
}

@Composable
fun ProfileHeader(userId: String) {
    Row(verticalAlignment = Alignment.CenterVertically) {
        AsyncImage(model = "https://example.com/avatars/$userId",
            contentDescription = "User avatar")
        Spacer(modifier = Modifier.width(12.dp))
        Text(text = "Benutzer #$userId", style = MaterialTheme.typography.headlineMedium)
    }
}

@Composable
fun StatsRow(posts: Int, followers: Int) {
    Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly) {
        StatItem("Posts", posts)
        StatItem("Followers", followers)
    }
}

@Composable
fun StatItem(label: String, value: Int) {
    Column(horizontalAlignment = Alignment.CenterHorizontally) {
        Text(text = "$value", style = MaterialTheme.typography.headlineSmall)
        Text(text = label, style = MaterialTheme.typography.bodySmall)
    }
}

Im Beispiel ist jede Composable-Funktion für ihren Teil des Bildschirms verantwortlich: ProfileScreen verwaltet den Gesamtzustand und die Komposition der Kindfunktionen, ProfileHeader zeigt Avatar und Namen an, und StatsRow zeigt einen Statistikblock. Dieser Ansatz folgt dem Prinzip der einzelnen Verantwortung und vereinfacht die Wiederverwendung von Komponenten.

Arten von Composable-Funktionen und ihre Zwecke

In Jetpack Compose gibt es drei Haupttypen von Composable-Funktionen. Der erste Typ — Container (Row, Column, Box, LazyColumn) — bestimmen die Anordnung der Kindelemente. Der zweite Typ — Anzeigeelemente (Text, Image, Icon, Button) — rendern bestimmte UI-Komponenten. Der dritte Typ — benutzerdefinierte Composable-Funktionen — kombinieren eingebaute Komponenten zu wiederverwendbaren Blöcken.

Container unterscheiden sich von regulären Elementen dadurch, dass sie ein Content-Lambda akzeptieren — den letzten Parameter vom Typ @Composable () -> Unit. Dieser Mechanismus ermöglicht den Aufbau verschachtelter UI-Bäume: Jeder Container erzeugt eine Kindkomposition mit eigenem Kontext und Speicherbereich.

Benutzerdefinierte Composable-Funktionen werden in zwei Untertypen unterteilt: smarte (smart) und stumme (dumb). Smarte Funktionen verwalten Zustand und Logik — sie enthalten Aufrufe von remember, LaunchedEffect und anderen Compose-APIs. Stumme Funktionen erhalten alle Daten über Parameter und zeigen sie nur an. Die Trennung in smarte und stumme Komponenten verbessert die Testbarkeit und die Wiederverwendbarkeit des Codes.

TypBeispielZweck
ContainerColumn, Row, BoxVerwaltung der Anordnung von Kindelementen
ElementText, Image, ButtonAnzeige von Inhalten und Eingabebehandlung
BenutzerdefiniertProfileCard, UserListKombination von Standardkomponenten

@Composable und Wiederverwendung von Komponenten

Der Hauptvorteil der @Composable-Annotation ist die Möglichkeit, wiederverwendbare UI-Komponenten ohne Vererbung und komplexe Klassenhierarchien zu erstellen. Im Gegensatz zum View-System, wo jedes benutzerdefinierte Element die Erstellung einer Java-Klasse mit Konstruktoren erforderte, ist eine Composable-Komponente einfach eine Kotlin-Funktion mit Parametern.

Zur Sicherstellung der Wiederverwendbarkeit wird das Slot-API-Muster verwendet, bei dem eine Composable-Funktion Content-Lambdas für verschiedene Bereiche ihres Layouts akzeptiert. Beispielsweise kann eine Card-Komponente separate Inhalte für Kopfzeile, Hauptteil und Fußzeile akzeptieren, was sie universell für jeden Bildschirm der Anwendung macht.

Modifikatoren (Modifier) spielen eine Schlüsselrolle bei der Wiederverwendbarkeit: Sie ermöglichen die Konfiguration von Abständen, Größen, Klicks und Animationen ohne Änderung der Komponente selbst. Es wird empfohlen, Modifier immer als Parameter einer Composable-Funktion mit einem Standardwert zu übergeben: Modifier = Modifier — dies ist eine Standardpraxis, die in den offiziellen Google-Bibliotheken üblich ist.

kotlin
@Composable
fun SectionCard(
    modifier: Modifier = Modifier,
    title: String,
    content: @Composable () -> Unit
) {
    Card(modifier = modifier) {
        Column(modifier = Modifier.padding(16.dp)) {
            Text(text = title, style = MaterialTheme.typography.titleMedium)
            Spacer(modifier = Modifier.height(8.dp))
            content()
        }
    }
}

Dank der Slot-API kann die SectionCard-Komponente auf verschiedenen Bildschirmen mit unterschiedlichen Inhalten verwendet werden — Formularen, Listen, Textblöcken. Die Kombination von Modifikatoren und der Slot-API macht Compose-Komponenten äußerst flexibel, ohne die Typsicherheit zu verlieren, die Kotlin bietet.

Häufig gestellte Fragen

Was ist der Unterschied zwischen @Composable und einer normalen Kotlin-Funktion?

Eine @Composable-Funktion wird im Kompositionskontext ausgeführt und kann Zustand lesen, wobei sie bei Änderung automatisch neu startet. Normale Kotlin-Funktionen haben keinen Zugriff auf Zustandsverfolgungsmechanismen und nehmen nicht am Aufbau des UI-Baums teil.

Kann eine Composable-Funktion von einer normalen Funktion aufgerufen werden?

Nein, Composable-Funktionen können nur von anderen Composable-Funktionen aufgerufen werden, da ein spezieller Kompositionskontext erforderlich ist. Zur Integration von Compose-Code mit normalem Kotlin wird die setContent { }-Methode der Activity oder ComposeView im View-System verwendet.

Warum werden Composable-Funktionen mit einem Großbuchstaben geschrieben?

Dies ist eine in der Compose-Community übliche Namenskonvention. Der Großbuchstabe unterscheidet UI-Komponenten visuell von gewöhnlichen Funktionen, indem er den Klassenbenennungsregeln folgt. Es ist keine Compiler-Anforderung, sondern eine empfohlene Praxis in der Google-Dokumentation.

Wie viele Composable-Funktionen können auf einem Bildschirm sein?

Es gibt keine Begrenzung der Anzahl. In der Praxis kann ein großer Bildschirm 50–100 Composable-Funktionen enthalten, einschließlich eingebauter Komponenten (Text, Button) und benutzerdefinierter. Compose optimiert den Funktionsbaum und führt nur diejenigen aus, deren Eingabedaten sich geändert haben.

Kann eine Composable-Funktion einen Wert zurückgeben?

Normalerweise geben Composable-Funktionen Unit zurück, da ihre Aufgabe der Aufbau der UI ist. Es gibt jedoch spezialisierte Funktionen wie remember und derivedStateOf, die mit @Composable markiert sind und Werte zurückgeben. Dies ist eine Ausnahme, nicht die Regel.

Zusammenfassung

  • @Composable — Annotation zur deklarativen UI-Beschreibung in Jetpack Compose
  • Composable-Funktionen werden nur innerhalb anderer Composable-Funktionen in einem speziellen Kontext aufgerufen
  • Idempotenz — jede wiederholte Ausführung mit denselben Argumenten erzeugt dieselbe UI
  • Nebeneffekte sind im Funktionskörper verboten — nur über LaunchedEffect und SideEffect
  • Slot-API und Modifier gewährleisten die Wiederverwendung von Komponenten ohne Vererbung
  • Container-Funktionen (Row, Column, LazyColumn) akzeptieren Content-Lambdas für verschachtelte Elemente
  • Empfehlung: Modifier als Parameter jeder benutzerdefinierten Composable-Funktion mit Standardwert übergeben

Wir entwickeln eine mobile Applikation schlüsselfertig

IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.

Projekt besprechen

Lesen Sie auch