Kotlin Multiplatform + Kotlin/Native: alternatywa dla Xamarin?
Czy Kotlin Multiplatform i Kotlin/Native mogą zastąpić Xamarin? Architektura demo dla Androida i iOS, konfiguracja Gradle, moduły common, expect/actual, warstwa danych oraz plusy i ograniczenia podejścia.
Mateusz Kopta
Wprowadzenie
Kotlin 1.2 przyniósł eksperymentalne Kotlin Multiplatform Projects, które pozwalają współdzielić kod między platformami JVM (Android, desktop, web). Równolegle Kotlin/Native kompiluje Kotlin bez VM do natywnych binariów na iOS, macOS czy systemy wbudowane.
Połączmy te technologie i zbudujmy prostą, mobilną aplikację na Android i iOS: przeglądarkę zdjęć z NASA Astronomy Picture of the Day.
Build system i IDE
Multiplatform opiera się wyłącznie na Gradle.
Dostępne są template w IntelliJ 2017.3 oraz wtyczka Kotlin/Native do AppCode 2018.1.1. W praktyce wygodnie jest użyć Android Studio do modułów Android i common oraz Xcode do części iOS.
Struktura projektu
- Android: klasyczna aplikacja zależna od modułu platform-android.
- iOS: projekt Xcode, który dołącza platform-ios jako ogólny framework obj-c.
- Common: współdzielony moduł z czystym Kotlinem, bez zależności platformowych. Deklaruje API wymagające platformowych implementacji za pomocą słowa kluczowego expect. Moduły platform-android i platform-ios dostarczają actual implementacje.
- Platform-android i platform-ios: implementacje zależne od platformy oraz dodatkowy kod natywny. Każdy moduł platformowy implementuje pojedynczy moduł common.
W module common dostępna jest jedynie wersja common standardowej biblioteki, kotlin-stdlib-common, co ogranicza dostępne API.
Tworzenie i konfiguracja
- Common: zależność wyłącznie od kotlin-stdlib-common. Opcjonalnie włączone coroutines jako funkcja eksperymentalna.
- Platform-android: moduł biblioteczny Android (com.android.library) z mechanizmem actual i zależnością expectedBy na common.
- Platform-iOS: użycie wtyczki Kotlin/Native (Konan) w Gradle do budowy frameworka dla iphone oraz iphone_sim, z włączonymi optymalizacjami i debugiem. Również expectedBy na common.
- Aplikacja Android: zależność od platform-android.
- Aplikacja iOS: budowana w Xcode, osadza wygenerowany AstronomyPictureOfTheDay.framework.
Asynchroniczność i coroutines
W momencie tworzenia projektu Kotlin/Native nie wspierał jeszcze coroutines. Aby zachować styl programowania zbliżony do async/await, zdefiniowano wspólny interfejs w common i dostarczono platformowe implementacje przez expect/actual. To umożliwia spójne API asynchroniczne przy jednoczesnym wykorzystaniu natywnych prymitywów na każdej platformie.
Warstwa dostępu do danych
- Endpoint: https://api.nasa.gov/planetary/apod?date=[date]&hd=true&api_key=[api_key]
- Odpowiedź zawiera m.in. date, explanation, hdurl, media_type, service_version, title, url.
- Wspólny model danych znajduje się w module common.
- Zapytania i parsowanie są realizowane natywnie na platformach: na Androidzie Retrofit + Gson, na iOS Alamofire + SwiftyJSON.
Takie podejście trzyma sieć i parsowanie blisko platformy, a jednocześnie pozwala współdzielić modele i logikę sterującą.
Reprezentacja daty w common
Użycie String do daty jest niewygodne przy nawigacji dzień wstecz/naprzód. Z powodu ograniczeń kotlin-stdlib-common przygotowano własną abstrakcję daty w module common z implementacjami actual:
- Android: JodaTime
- iOS: NSDate (Foundation)
Dzięki interoperacyjności Kotlin/Native z Objective-C/Swift można bezpośrednio wywoływać API Foundation czy UIKit z kodu w Kotlinie, mimo że cały moduł jest pisany w Kotlin.
MVP: Presenter i View
W module common zdefiniowano prosty zestaw interfejsów Presenter i View (MVP). Platformowe ekrany implementują View, a Presenter i logika nawigacji pozostają współdzielone.
Integracja w aplikacjach
Android i iOS dołączają moduł common, wstrzykują platformowe implementacje repozytoriów, narzędzi czasu i asynchroniczności, a następnie wiążą Presenter z natywnym UI. Dzięki temu duża część logiki pozostaje identyczna na obu platformach.
Podsumowanie
Kotlin Multiplatform + Kotlin/Native już dziś pozwalają współdzielić kluczową logikę między Androidem i iOS, przy zachowaniu natywnych interfejsów i bibliotek.
Plusy:
- Wspólny język i modele danych
- Natywny dostęp do API (Retrofit, UIKit, Foundation)
- Brak VM po stronie iOS, czyste binaria
Ograniczenia:
- Status eksperymentalny i uboższe kotlin-stdlib-common
- Rozdzielone narzędzia (Gradle + Xcode)
- W ówczesnym stanie brak pełnego wsparcia coroutines w Kotlin/Native, konieczne mostkowanie expect/actual
Dla zespołów pracujących w Kotlinie to realna alternatywa dla Xamarin, zwłaszcza gdy cele obejmują natywne UI i współdzielenie logiki. Warto śledzić rozwój — kolejne wydania upraszczają konfigurację i poszerzają wsparcie bibliotek.
Potrzebujesz wsparcia technologicznego?
Porozmawiajmy o Twoim projekcie — od discovery po wdrożenie.
Umów konsultacjęChcesz wiedzieć więcej?
Sprawdź inne artykuły lub porozmawiajmy o Twoim projekcie
Wszystkie artykuły Zaprojektujmy Twoją aplikację AI