Mit dem Slogan "Build better apps faster" wirbt Google mit viel Stolz für die neue Jetpack Compose Library. Nach rund einem halben Jahr in Gebrauch lässt sich die Aussage treffen; da ist definitiv etwas dran. Der Weg zurück zum ursprünglich gängigen Layoutsystem ist schwierig rechtzufertigen. Nach rund einem halben Jahr im Einsatz ist uns klar, dass wir von nun an nur noch darauf setzen möchten.
Was ist Jetpack Compose?
Jetpack Compose ist das neue, moderne Toolkit für Android. Damit können User Interfaces (UI) für Android Apps einfacher und schneller erstellt werden. Jetpack Compose schöpft das volle Potenzial von Kotlin aus, der Standardsprache von Android. Damit wird auch gleich der grösste Unterschied zur herkömmlichen Art Android-UIs zu bauen aufgedeckt. Anstatt mit XML Dateien das UI zu gestalten, wird Kotlin eingesetzt. So wird das Layout nun mit beschreibenden Ausdrücken dargestellt, welche sich fast wie ein Text lesen lassen. Anbei ein Vergleich wie sich ein Titel und ein kleiner Text darunter abbilden lassen:
An der jährlichen Tech-Konferenz von Google, Google I/O, wurde 2019 die erste Entwicklungsversion von Jetpack Compose vorgestellt. Diese wurde damals noch explizit als "pre-alpha" und sehr unstabil vermarktet. Etwas mehr als 2 Jahre, eine Pandemie und zahlreiche Alpha & Beta Releases später, steht Jetpack Compose seit Juli 2021 in Version 1.0 bereit. Durch die lange Entwicklungsphase konnten viele Feedbacks von der Community berücksichtigt werden.
In den letzten paar Monaten konnten wir bereits einiges an Wissen dazu aufbauen. Begonnen hatte dies mit der #AndroidDevChallenge im vergangenen April. Dort wurden verschiedene Aufgaben präsentiert, welche mit Jetpack Compose gelöst werden sollen. Wir konnten durch die Teilnahme sogar einige Preise gewinnen.
Wir fordern uns gerne selber heraus und erweitern unser Wissen - das wird auch mal belohnt! Unser Android Dev @yannickpulver wurde fürs Mitmachen an der #AndroidDevChallenge von @Google mit fancy #JetpackCompose Trophäe und Poster beschenkt✨🚀 pic.twitter.com/HPtGxi1Hfm
— Apps with love (@appswithlove) May 12, 2021
In der Zwischenzeit konnten wir Jetpack Compose bereits in einigen Projekten umsetzen. In den folgenden Abschnitten sind Punkte erwähnt, die uns besonders überzeugten.
Geschwindigkeit in der Entwicklung
In dem ursprünglichen Layoutsystem von Android gibt es die sogenannte Komponente RecyclerView. Diese Komponente ist verantwortlich für die Darstellung von scrollbaren Listen wie man sie beispielsweise vom Instagram Feed her kennt. Daher ist die RecyclerView fast in jeder App zu finden. Das Aufsetzen einer solchen Liste benötigt aber gerne mal mehrere Hundert Zeilen Code. Wenn nebst Posts auch noch weitere Elemente dargestellt werden sollen, dann wird es schnell unübersichtlich.
In Jetpack Compose gibt es hierfür die Komponente LazyColumn und LazyRow. Es ist erstaunlich, wie viel effizienter sich dies mit Jetpack Compose bauen lässt. Auch Menschen ohne Programmierkenntnisse können erkennen, um was es sich hierbei handelt:
Dieses Muster von beschreibenden Code zieht sich durch das ganze Framework. Genannt wird diese Form “Deskriptives UI”.
Deskriptives UI
Der Code ist wesentlich lesbarer als im alten Layoutsystem. Früher mussten die Layouts in XML definiert und in Kotlin angesprochen werden. In Jetpack Compose wird dies vereint und so kann nun alles in Kotlin geschrieben werden.
Dies wird erreicht durch den Einsatz von deskriptiven beziehungsweise beschreibendem UI. Diese Art von Layout ist bekannt von anderen Sprachen wie Flutter oder SwiftUI. Hier ein Beispiel, wie der Code für eine Liste von Texten auf den verschiedenen Plattformen aussieht:
Obwohl der Code teilweise grosse Unterschiede aufweist, ist vieles ähnlich aufgebaut. Dies ist durchaus zu Gunsten der Entwickler*innen. Sie können sich nun plattformunabhängig über die grobe beschreibende Struktur unterhalten.
Die Komponenten in Jetpack Compose sind einfach benannt und effizient zu bedienen. Die zweijährige Entwicklungsphase hat sich durchaus gelohnt. Mehr Informationen wie sich Jetpack Compose und Swift UI ähnlich sind zeigt auch der Blog von Mohit auf.
States
Mit Jetpack Compose wurde der Begriff "Zustand" bzw. "State" zentraler als je zuvor. Der State gibt vor wie sich das UI verhalten soll. Sind die Daten noch nicht geladen? Gibt es einen Fehler? Wie viele Elemente sollen in der Liste gezeigt werden? All dies wird in einem zentralen State definiert. Je nach State, wird das UI anders dargestellt. Jetpack Compose verwendet Algorithmen, um nur die Änderungen neu zu zeichnen. Dieser Vorgang nennt sich "Recomposition".
Die Verwendung von States brachte aber auch einen mentalen Shift mit sich. Gewohnte Abläufe vom alten UI System müssen teilweise komplett neu durchdacht werden. Die Vorteile liegen hier aber auf der Hand. Die Kontrolle liegt in den Händen der Entwickler*innen. Keine Abläufe passieren mehr auf "magische" Weise. 🧙♀️
Ein kleines Beispiel: Um ein Eingabefeld zu erzeugen, muss angegeben werden woher der Wert kommt und was damit passiert, wenn die Eingabe erfolgt. Wird dies nicht gemacht, so wird auch nichts neues dargestellt.
Über den Parameter "onValueChange" kann mitgegeben werden, was passiert wenn die Eingabe erfolgt. Würde der State nicht gesetzt werden, so würde sich für den Nutzer auch nichts auf dem Screen ändern. Das sieht dann so aus, als würde die Eingabe nicht funktionieren.
Rückwärtskompatibilität (Interoperability)
Die Integration in das bestehende Layoutsystem war sehr wichtig für Google. Viele der Open Source Libraries von anderen Entwicklern waren zu Beginn noch nicht kompatibel. Deshalb musste ein Weg gefunden werden, diese dennoch ins neue System zu integrieren. In Jetpack Compose wird dies mit der “AndroidView” Komponente gelöst.
Mit dem “factory” Parameter kann mitgegeben werden, welche (alte) View erstellt werden soll. Mit dem "update" Parameter wird Code mitgegeben, welcher bei jeder Recomposition wieder ausgeführt wird.
Wir haben die "AndroidView" zum Beispiel eingesetzt um Mapbox mit dem Jetpack Compose System kompatibel zu machen. Dabei stiessen wir auf etliche Probleme, welche aber meistens mit der Handhabung des States zu tun hatten. Davon abgesehen können alte Komponenten relativ leicht mit Jetpack Compose verwendet werden. Es braucht nur etwas Zeit um mit der Handhabung vertraut zu werden.
Nice to know
In diesem Abschnitt möchte ich noch auf ein paar Sachen eingehen, welche bei Jetpack Compose besonders überzeugen.
spacedBy
Eine meiner Lieblingsfunktionen von Jetpack Compose ist spacedBy. Mit dieser Funktion kann der Zwischenraum zwischen Elementen in Listen definiert werden. Das dies so einfach machbar ist, ist einfach toll. Früher war dies - nunja - nicht einfach.
Modifier
Praktisch jede Standardkomponente besitzt die Möglichkeit einen Modifier mitzugeben. Über den Modifier wird definiert wie ein Element aussieht, welche Grösse es hat, ob es klickbar ist, und vieles mehr. Ein kleines Beispiel:
Es können auch mehrere Modifier vom gleichen Typ (im Beispiel oben das Padding) miteinander verknüpft werden. So erhält die Text-Komponentel einen Rahmen, welcher vom Text selbst etwas entfernt ist, sowie nochmals Abstand ausserhalb des Rahmens. Etliche verschachtelte komplizierte Layouts sind damit Geschichte.
Performance
Bei der Entwicklung ist uns aufgefallen, dass die "debug" Builds der Apps teilweise langsam sind. Beispielsweise lassen sich grosse Listen manchmal nicht ohne Ruckler scrollen. Diese Probleme verschwinden aber sobald ein "release" Build verwendet wird. So wie sie auch im Play Store ausgeliefert werden. Es ist anzunehmen, dass dies in zukünftigen Versionen von Compose verbessert wird. In der Zwischenzeit steht diese Anweisung auch auf der offiziellen Android Developer Seite.
Accompanist
Die Accompanist Libraries beinhalten verschiedene "Bleeding Edge" Funktionen, welche noch nicht in Jetpack Compose zu finden sind. So gibt es Komponenten wie Pager, Swipe to Refresh, oder auch Navigationsübergänge in diesen Libraries zu finden. Die Libraries wurden von Chris Banes (ehem. Google Entwickler) ins Leben gerufen und sind mittlerweile als offizielle Google Libraries verfügbar. Die Verwendung der Accompanist Libraries ist wie der Name bereits sagt (engl. Accompanist = Begleiter*in), in Jetpack Compose Projekten sehr üblich und kaum wegzudenken. Früher oder später werden diese Funktionen dann womöglich in den offiziellen Libraries erscheinen.
Compose Multiplatform
Ende 2021 wurde auch die erste Version von “Compose Multiplatform” veröffentlicht. Damit soll es nun möglich sein Apps für Web, Desktop und Android alles in einem zu entwickeln. So ähnlich wie dies mit Flutter möglich ist. Bislang konnten wir noch einen Einsatzzweck dafür finden, aber wir werden die laufenden Entwicklungen sicherlich im Auge behalten.
Roadmap
Es liegt auf der Hand, dass Jetpack Compose noch nicht so ausgereift ist wie das herkömmliche Layoutsystem. Zusammen mit der “Accompanist Library” wird aber bereits jetzt praktisch alles möglich gemacht. Für alles was noch fehlt hat Google eine Roadmap veröffentlicht. Dort steht was in den nächsten Monaten / Jahren noch alles für Jetpack Compose entwickelt werden sollte.
Fazit
Jetpack Compose erleichtert die Erarbeitung von UI’s enorm. Animationen sind oft kinderleicht zu implementieren oder per se “gegeben”. Layouts können wesentlich schneller entwickelt werden. Dabei macht es auch richtig viel Spass! Es gibt definitiv genug Gründe, weshalb Compose für zukünftige Projekte eingesetzt werden soll. Ich hoffe wirklich sehr das Jetpack Compose nicht auf der “Killed by Google” Liste endet. ;)