Kotlin-Updates: Jetpack Compose 1.0

In Teil 7 der Kotlin-Updates-Serie werfe ich einen Blick auf Jetpack Compose. Als ich mein Kotlin-Buch im Herbst 2020 fertiggestellt habe, gab es erst eine Alpha-Version dieses neuen UI-Frameworks. Mittlerweile ist Jetpack Compose fast fertig. Weil die mittlerweile stattgefundenen Änderungen umfassend waren, habe ich das betroffene Kapitel 26 vollständig aktualisiert. Sie finden die PDF-Datei am Ende dieses Blog-Beitrags zum Download. Das Kapitel bietet einen guten Einstieg in die Zukunft der Android-Programmierung!

Dieser Text bezieht sich auf die folgenden Versionsnummern:

Android Studio Arctic Fox = Android Studio 2020.3.1 (veröffentlicht im Juli 2021)
Kotlin: 1.5.10
Jetpack Compose: 1.0
Gradle: 7.0

Anmerkung: Die ursprüngliche Fassung dieses Artikels wurde nach den Releases von Jetpack Compose 1.0 und Android Studio Arctic Fox nochmals aktualisiert.

Anmerkung 2 (August 2021): Mittlerweile funktioniert es auch mit Kotlin 1.5.21 und Compose 1.0.1.

Was ist Jetpack Compose?

Jetpack Compose eröffnet einen neuen Weg, um Benutzeroberflächen für Android-Apps zusammenzustellen: Anstatt die Aktivitäten und Steuerelemente wie bisher in einem grafischen Editor einzurichten und intern im XML-Format zu speichern, wird dazu nun Kotlin-Code mit der Annotation @Composable verwendet.

Der riesige Vorteil von Jetpack Compose besteht darin, dass Sie sich nicht mehr länger mit dem sperrigen Layouteditor und unübersichtlichen Layoutregeln herumärgern müssen. Vielmehr können Sie das Erscheinungsbild Ihrer App durch verhältnismäßig kompakten Code ausdrücken und es direkt in Android Studio ansehen und testen. Das geht schneller, lässt sich besser dokumentieren und rascher ändern. Interessanterweise beschreitet Apple mit SwiftUI genau denselben Weg. Ein weiterer Vertreter in der aktuell rasch wachsenden Familie von deklarativen UI-Frameworks ist Flutter (siehe https://flutter.dev). Es gibt also aktuell einen regelrechten Trend hin zu sogenannten deklarativen UI-Frameworks.

Licht und Schatten

Das Konzept von Jetpack Compose begeistert mich. Das liegt daran, dass ich lieber Code verfasse als umständlich per Maus oder Trackpad in versteckten Dialogen nach Layoutoptionen zu suchen.

Dessen ungeachtet ist das Compose-Konzept keineswegs frei von Problemen. Ein offensichtlicher Nachteil besteht im exzessiven Lambda-Einsatz, der zu einer Klammernhölle wie in JavaScript führt. Sobald Ihre App mehr als »Hello World!« am Bildschirm darstellen soll, lassen sich schier endlose Verschachtelungen von Compose-Funktionen kaum vermeiden.

Den Einstieg in Compose erschweren zudem unzählige Anleitungen in Blogs und auf Stack Overflow, die sich auf frühe Compose-Versionen beziehen und längst nicht mehr funktionieren. Ebenfalls irritierend sind die relativ langen Build-Zeiten, die einem flotten interaktiven Layoutprozess im Wege stehen.

Jetpack Compose ist übrigens eine radikale Absage an Java: Jetpack Compose erfordert ein spezielles Kotlin-Compiler-Plugin und kann nicht durch Java-Code genutzt werden.

Voraussetzungen

Damit Sie Jetpack Compose ausprobieren können, müssen Sie Android Studio Arctic Fox verwenden.

Falls Sie vorher eine Testversion von Android Studio installiert haben, kommt es beim Start der finalen Version womöglich zur Fehlermeldung Missing essential plugin: org.jetbrains.android. Abhilfe: Entfernen Sie aus .config/Google/AndroidStudio2020.3/disabled_plugins.txt die Zeile org.jetbrains.android. Hintergründe: stackoverflow

Die Kotlin-Version ist in den beiden build.gradle-Dateien (Project und Module) mit 1.5.10 festgelegt. Neuere Versionsnummern wurden im Juli 2021 nicht unterstützt und führten zum Build-Fehler Execution failed for task app:compileDebugKotlin.)

Von der Alpha-Version zu Version 1.0

Es gibt unzählige Änderungen in Jetpack Compose 1.0 im Vergleich zu der im Buch beschriebenen Alpha-Version:

  • Die Klassen und Methoden sind innerhalb des Frameworks vollkommen neu organisiert. Deswegen sind nun ganz andere Importe erforderlich.

  • Beim Erzeugen von Images und Icons muss zwingend der Parameter contentDescription angegeben werden, der das Bild oder Symbol beschreibt (zur Not mit null).

  • Viele Namen von Funktionen, Methoden, Parametern und Eigenschaften haben sich geändert. Manche Parameter sind zugunsten zusätzlicher Modifier-Eigenschaften ganz verschwunden.

AppCompatActivity            -> ComponentActivity
bodyContent                  -> content
ContextAmbient               -> LocalContext
gravity                      -> align
horizintalGravity            -> horizontalAlignment
icon                         -> content
keyboardType                 -> keyboardOptions
imageResource                -> painterResource
preferredHeight/-Size/-Width -> requiredHeight/-Size/-Width
showDecoration               -> showSystemUi
Stack                        -> Box
verticalGravity              -> verticalAlignment

Es ist nahezu unmöglich, vorhandenen Code, der eine alte Version von Jetpack Compose verwendet, auf die gerade aktuelle Version zu adaptieren — ganz einfach weil die Anzahl der Änderungen zu groß ist. Effizienter ist es in der Regel, den Code in kleinen Stücken neu zu implementieren.

Weil mir die Auflistung unzähliger Änderungen hier nicht zielführend erscheint, habe ich mich dazu entschlossen, den Text sowie alle Beispiele in Kapitel 26 vollständig zu aktualisieren. Sie finden die Download-Links am Ende dieses Blog-Beitrags.

UI-Status erhalten mit rememberSaveable

remember-Variablen und die damit verbundenen Steuerelemente bzw. Compose-Funktionen verlieren ihren Status, wenn die Oberfläche vollständig neu aufgebaut werden muss. Das ist beispielsweise der Fall, wenn der Nutzer einer App sein Smartphone ins Querformat dreht oder wenn die Nutzerin in den Dark Mode wechselt. In der Alpha-Version von Jetpack Compose war dieses Problem noch ungelöst. Das hat sich zum Glück geändert. Sie deklarieren nun die entsprechende Variable einfach mit rememberSaveable:

// erhält den Status des Klick-Zählers auch bei einer 
var cnt by rememberSaveable { mutableStateOf(0) }

Tastatur ausblenden mit dem LocalSoftwareKeyboardController

Zur Steuerung der Tastatur sieht Jetpack Compose das noch experimentelle Objekt LocalSoftwareKeyboardController vor:

@ExperimentalComposeUiApi
@Composable
fun MyComposeFunction() {
    val kbdController = LocalSoftwareKeyboardController.current
    ...
    Button(content = { Text("OK") },
           onClick = { kbdController?.hide() } )
    ...
}

Quellen und Links

Jetpack Compose

Android Studio

Downloads

Die aktualisierten Beispielprojekte zu Kapitel 26 können Sie hier herunterladen:

https://kofler.info/uploads/kotlin/kap26.zip

Beachten Sie, dass Sie Android Studio Arctic Fox installieren müssen, um die Beispiele auszuprobieren!

Das vollständig aktualisierte Kapitel 26 mit einem Umfang von 38 Seiten finden Sie hier:

https://kofler.info/uploads/kotlin/jetpack-compose-1.0.pdf

Der geänderte Text wurde nicht korrekturgelesen und wird daher den einen oder anderen Tipp- und Rechtschreibfehler enthalten.

Die Kotlin-Updates-Serie

Weitere Kotlin-Update-Artikel finden Sie hier auf meiner Website:

https://kofler.info/tag/kotlin-updates