Eine App für Android und iOS zu entwickeln, bedeutete lange Zeit doppelte Arbeit: einmal in Kotlin/Java für Android, einmal in Swift für iOS. Kotlin Multiplatform (KMP) verspricht hier einen pragmatischen Mittelweg – du teilst die Geschäftslogik plattformübergreifend in Kotlin und behältst gleichzeitig die Freiheit, native Oberflächen oder sogar geteilte UI zu nutzen. Seit JetBrains KMP für stabil erklärt hat, ist es eine ernstzunehmende Option für viele Projekte geworden. Dieser Artikel erklärt das Konzept und wann sich der Einsatz lohnt.
Die Grundidee: Logik teilen, UI nativ halten
Der Kerngedanke von KMP unterscheidet sich grundlegend von manch anderem Cross-Platform-Ansatz. Statt eine komplette App in einer fremden Umgebung zu erzwingen, teilst du gezielt das, was sich gut teilen lässt:
- Geteilt: Geschäftslogik, Netzwerkschicht, Datenmodelle, Validierung, lokale Datenbank, Caching – alles, was plattformunabhängig ist.
- Nativ pro Plattform: Optional die Benutzeroberfläche – mit Jetpack Compose auf Android und SwiftUI auf iOS – sowie plattformspezifische APIs.
Dieser Ansatz hat einen großen Charme: Die fehleranfälligste und am häufigsten geänderte Logik schreibst und testest du nur einmal, während die UI sich nach wie vor zu 100 Prozent nativ anfühlen kann. Du gibst also nicht das native Look-and-Feel auf, um Code zu sparen.
Wie der gemeinsame Code kompiliert wird
Kotlin ist nicht auf die JVM beschränkt. KMP nutzt verschiedene Kotlin-Compiler-Backends, um denselben Quellcode für unterschiedliche Zielplattformen zu übersetzen:
- Kotlin/JVM erzeugt Bytecode für Android (und JVM-Backends).
- Kotlin/Native kompiliert direkt zu nativem Maschinencode für iOS – das Ergebnis ist ein Framework, das sich in Xcode wie eine native Bibliothek einbinden lässt.
- Kotlin/JS und Kotlin/Wasm ermöglichen zusätzlich Web-Ziele.
Für die iOS-Entwickler im Team fühlt sich das geteilte Modul an wie eine ganz normale Bibliothek: Sie importieren es in Swift und rufen Kotlin-Funktionen auf, als wären es Swift-APIs.
expect und actual: Plattformspezifisches im geteilten Code
Manchmal braucht geteilter Code Zugriff auf plattformspezifische Funktionen – etwa die aktuelle Systemzeit, Zufallszahlen, sicheren Speicher oder Datenbankzugriffe. Dafür gibt es den expect/actual-Mechanismus:
- Im gemeinsamen Modul deklarierst du mit
expecteine Funktion oder Klasse – quasi ein Versprechen, dass jede Plattform eine Implementierung liefert. - In den plattformspezifischen Quellordnern lieferst du mit
actualdie konkrete Umsetzung – einmal mit Android-APIs, einmal mit iOS-APIs.
So bleibt deine geteilte Logik sauber und plattformneutral, während die wenigen Stellen, die wirklich plattformspezifisch sein müssen, klar abgegrenzt sind. In der Praxis übernehmen oft Bibliotheken diese Arbeit für dich, sodass du expect/actual seltener selbst schreiben musst, als man zunächst denkt.
Das Ökosystem: Bibliotheken für KMP
Ein Cross-Platform-Ansatz steht und fällt mit den verfügbaren Bibliotheken. Das KMP-Ökosystem ist in den letzten Jahren deutlich gereift:
- Ktor – HTTP-Client für plattformübergreifende Netzwerkanfragen.
- kotlinx.serialization – JSON-Serialisierung im geteilten Code.
- SQLDelight – typsichere SQL-Datenbankzugriffe über Plattformen hinweg.
- Koin – Dependency Injection für KMP-Projekte.
- kotlinx.coroutines – asynchrone Programmierung, die auf allen Zielen funktioniert.
Mit dieser Werkzeugkette lässt sich eine komplette Datenschicht – vom API-Aufruf über die Serialisierung bis zur lokalen Speicherung – einmal schreiben und auf beiden Plattformen nutzen.
Compose Multiplatform: Auch die UI teilen
Wer noch mehr teilen möchte, kann zu Compose Multiplatform greifen. Dabei wird Jetpack Compose – Googles UI-Toolkit für Android – auf weitere Plattformen portiert. JetBrains hat Compose für Desktop, Web und mittlerweile auch für iOS verfügbar gemacht.
Damit lässt sich nicht nur die Logik, sondern auch ein großer Teil der Oberfläche plattformübergreifend in Kotlin schreiben. Auf iOS wird die Compose-UI gerendert und über die nötigen Brücken in die native Umgebung eingebettet. Für Projekte, in denen eine konsistente UI über alle Plattformen hinweg wichtiger ist als 100-prozentig native Komponenten, ist das ein attraktiver Weg. Wer hingegen jede Plattform nativ fühlen lassen will, teilt nur die Logik und baut die UI je nativ.
KMP im Vergleich zu Flutter und React Native
KMP ist nicht der einzige Cross-Platform-Ansatz. Die wichtigsten Unterschiede:
- Flutter nutzt Dart und rendert die gesamte UI über eine eigene Engine. Sehr konsistentes Aussehen, aber alles läuft außerhalb der nativen UI-Systeme. Einen ausführlicheren Vergleich der UI-Ansätze findest du im Artikel zu Flutter vs. SwiftUI.
- React Native nutzt JavaScript/TypeScript und bildet native Komponenten ab, mit einer Brücke zwischen JS und Nativem.
- KMP verfolgt den „logic-first"-Ansatz: maximale Flexibilität, weil du selbst entscheidest, wie viel du teilst – von nur der Datenschicht bis zur kompletten UI. Der Code läuft als echter nativer Maschinencode, nicht in einer Laufzeitumgebung.
Es gibt kein universelles „besser" – die Wahl hängt vom Team, den bestehenden Skills und den Anforderungen ab. Hast du bereits eine Android-App in Kotlin und möchtest schrittweise iOS bedienen, ist KMP oft der natürlichste und am wenigsten disruptive Weg.
Architektur eines KMP-Projekts
Ein typisches KMP-Projekt ist in Source-Sets gegliedert:
- commonMain – der geteilte Kotlin-Code, der auf allen Plattformen läuft.
- androidMain – Android-spezifische Implementierungen und Zugriffe auf das Android-SDK.
- iosMain – iOS-spezifischer Code, der auf Apple-Frameworks zugreift.
- commonTest – plattformübergreifende Tests für die geteilte Logik, die du nur einmal schreibst.
Ein bewährtes Muster ist es, ViewModels oder Presenter in den geteilten Code zu legen und nur die reine Darstellung pro Plattform zu implementieren. So teilst du auch die Zustandslogik und reduzierst plattformspezifischen Code auf ein Minimum.
Wann sich KMP lohnt – und wann nicht
KMP ist kein Allheilmittel. Es lohnt sich besonders, wenn:
- du beide Plattformen mit komplexer, geteilter Geschäftslogik bedienst;
- dein Team bereits Kotlin-Erfahrung mitbringt;
- dir natives Look-and-Feel und Performance wichtig sind, du aber Doppelarbeit bei der Logik vermeiden willst.
Weniger sinnvoll ist es, wenn du nur eine einzige Plattform bedienst, dein Team rein im Apple-Ökosystem zu Hause ist oder die App so klein ist, dass der Einrichtungsaufwand den Nutzen übersteigt. Für Tooling rund um App-Entwicklung und Datenkonvertierung findest du im kotsch.tech Webtools-Bereich nützliche Helfer wie JSON- und Text-Werkzeuge.
Häufige Fragen
Ist Kotlin Multiplatform produktionsreif?
Ja. JetBrains hat den Kern von Kotlin Multiplatform für stabil erklärt, und namhafte Unternehmen setzen es in produktiven Apps ein. Compose Multiplatform für iOS hat zuletzt ebenfalls große Fortschritte gemacht und einen stabilen Status erreicht.
Brauche ich für iOS trotzdem einen Mac?
Ja. Für das Bauen, Testen und Veröffentlichen der iOS-App benötigst du Xcode und damit macOS. KMP nimmt dir das Teilen der Logik ab, ersetzt aber nicht die Apple-Toolchain für den iOS-Teil.
Können iOS-Entwickler den Kotlin-Code nutzen, ohne Kotlin zu lernen?
Weitgehend ja. Das geteilte Modul wird als Framework bereitgestellt, das sich in Swift wie eine normale Bibliothek aufrufen lässt. Für tiefere Eingriffe oder das Schreiben geteilten Codes sind Kotlin-Kenntnisse natürlich hilfreich.
Muss ich Compose Multiplatform verwenden?
Nein. Du kannst nur die Logik teilen und die UI vollständig nativ mit Jetpack Compose und SwiftUI bauen. Compose Multiplatform ist eine optionale Erweiterung für alle, die auch die Oberfläche teilen möchten.
Wie steige ich am besten ein?
JetBrains bietet einen offiziellen KMP-Projektassistenten und ausführliche Tutorials. Ein guter Start ist, in einer bestehenden Android-App die Datenschicht in ein gemeinsames Modul auszulagern und schrittweise mehr Logik zu teilen, statt gleich alles auf einmal umzustellen.