Kotlin Multiplatform, platformlar arası geliştirmenin geleceği mi? Nasıl başlayacağınıza dair ipuçları
Yayınlanan: 2021-01-29Günümüzde, mobil geliştirmede uygulamaları daha hızlı yayınlama eğilimini gözlemleyebiliriz. Android ve iOS gibi farklı platformlar arasında ortak kod parçalarını paylaşarak geliştirme süresini kısaltmak için birçok girişimde bulunuldu. Bazı çözümler zaten popülerlik kazanırken, diğerleri hala geliştirme aşamasındadır. Bugün, ikinci grubun en yeni yaklaşımlarından birini tartışmak istiyorum – Kotlin Multiplatform Mobile (kısaca KMM).
Kotlin Multiplatform Mobil nedir?
KMM, öncelikle iş mantığını platformlar arasında paylaşmayı amaçlayan bir SDK'dır - çoğu durumda zaten aynı olması gereken kısım. Bu, paylaşılan bir modül için bir dizi çoklu derleyici sayesinde elde edilir. Örneğin, Android hedefi bir Kotlin/JVM varyantı kullanır ve iOS için bir Kotlin/Native varyantı vardır. Daha sonra tipik yerel uygulama projelerine paylaşılan bir modül eklenebilir ve kullanıcı arayüzünden sorumlu geliştiriciler, kullanıcılara tanıdık bir ortamda en iyi deneyimi sunmaya odaklanabilir – Android için Android Studio ve iOS için Xcode.
Kotlin Multiplatform vs Flutter
Şu anda, platformlar arası uygulama geliştirme için en popüler çözümlerden biri Flutter'dır. “Tek bir uygulama yaz ve her yerde çalıştır” kuralına odaklanmıştır – bu işe yarar, ancak yalnızca basit uygulamalar için. Gerçek durum senaryolarında, geliştiriciler, örneğin bir eklenti eksik olduğunda, boşlukları doldurmak için genellikle her platform için yerel kod yazmak zorunda kalırlar . Bu yaklaşımla, uygulama farklı platformlarda aynı görünür ve bu bazen arzu edilir, ancak bazı durumlarda belirli tasarım yönergelerini bozabilir.
Kendi uygulamanızı oluşturmaya hazır mısınız?
Flutter'ı seçinKulağa benzer gelse de Kotlin Multiplatform, platformlar arası bir çözüm değildir – tekerleği yeniden icat etmeye çalışmaz. Geliştiriciler bildikleri ve beğendikleri araçları kullanmaya devam edebilirler. Ağ istekleri yapmak, veri depolamak ve diğer iş mantığı gibi daha önce birden çok kez yazılmış olması gereken kod parçalarını yeniden kullanma sürecini basitleştirir .
Kotlin Multiplatform'un artıları ve eksileri
KMM'nin Artıları :
- Geliştirilen uygulama her platform için %100 yereldir – şu anda kullanılan kod ve üçüncü taraf kitaplıklarla entegre edilmesi kolaydır
- Kullanımı kolay – neredeyse tüm Android geliştiricileri Kotlin'i zaten kullanıyor, bu nedenle başlamaları için çok az ek bilgi gerekiyor
- Kullanıcı arayüzü, her hedef platform için bölünebilir - uygulama, herhangi bir ekosistemle tutarlı hissedecektir.
- Paylaşılan mantık , geliştiricilerin aynı anda her iki işletim sisteminde de yeni özellikler eklemesine ve hataları düzeltmesine olanak tanır
KMM'nin Eksileri :
- Birçok bileşen hala Alfa/Beta aşamasındadır ve potansiyel olarak kararsız olabilir veya gelecekte değişebilir
Hangi şirketler KMM kullanıyor?
Resmi siteye göre, şirketler bu teknolojiye giderek daha fazla ilgi duyuyor ve liste sürekli uzuyor. Bunlar arasında Autodesk, VMWare, Netflix veya Yandex gibi tanınmış markalar var.
Kotlin Multiplatform'a nasıl başlanır?
Derinlemesine bilgi için dalış yapmak için en iyi yer resmi rehberdir, ancak bu makalede, oldukça basit ama uygulama getirme ve görüntüleme olan bir “Merhaba Dünya”dan daha ilginç bir örnek göstermek istiyorum. Randall Munroe'nun en son çizgi romanı (CC BY-NC 2.5 altında lisanslanmıştır), başlığı xkcd.com API'den alınmıştır.
Ele alınacak özellikler:
- Proje kurulumu
- Paylaşılan modülde ağ oluşturma
- Hem Android hem de iOS için basit kullanıcı arayüzü
Not: Bu örneğin hem Android hem de iOS geliştiricileri için okunması kolay olmasını istedim, bu nedenle bazı yerlerde neler olup bittiğini netleştirmek için platforma özel bazı iyi uygulamaları kasıtlı olarak atladım.
Proje kurulumu
Öncelikle, bu projenin oluşturulması için her ikisi de gerekli olacağından , Android Studio ve Xcode'un en son sürümlerinin kurulu olduğundan emin olun . Ardından, Android Studio'da KMM eklentisini yükleyin. Bu eklenti birçok şeyi basitleştirir – yeni bir proje oluşturmak için Yeni Proje Oluştur'a tıklayın ve KMM Uygulaması'nı seçin.
Proje oluşturulduktan sonra , paylaşılan dizindeki build.gradle.kts
dosyasına gidin . Burada gerekli tüm bağımlılıkları belirtmeniz gerekir. Bu örnekte, ağ katmanı için kotlinx.serialization
, arka uçtan json yanıtlarını ayrıştırmak için kotlinx.serialization ve hepsini eşzamansız olarak yapmak için kotlin coroutines kullanacağız.
Basit olması için aşağıda, halihazırda mevcut olanlara eklenmesi gereken tüm bağımlılıkları gösteren listeler sunuyorum. Bağımlılıklar eklediğinizde, projeyi senkronize etmeniz yeterlidir (bir istem görünecektir). İlk olarak, serileştirme eklentisini eklentiler bölümüne ekleyin.
eklentiler { kotlin("plugin.serialization") sürüm "1.4.0" }
Ardından bağımlılıkları ekleyin.
kaynak Kümeleri { val commonMain alarak { bağımlılıklar { uygulama ("org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.0") application("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9-native-mt-2") uygulama ("io.ktor:ktor-client-core:1.4.1") uygulama ("io.ktor:ktor-client-json:1.4.1") uygulama ("io.ktor:ktor-client-serialization:1.4.1") } } val androidMain alarak { bağımlılıklar { uygulama("io.ktor:ktor-client-android:1.4.1") } } val iosMain alarak { bağımlılıklar { uygulama ("io.ktor:ktor-client-ios:1.4.1") } } }
Bu makalenin yazıldığı sırada, iOS'taki coroutines kitaplığının kararlı sürümüyle ilgili bazı sorunlar olduğunu belirtmekte fayda var - bu nedenle kullanılan sürüm yerel-mt-2 son ekine sahiptir (yerel çoklu kullanım anlamına gelir). Bu sorunun güncel durumunu buradan kontrol edebilirsiniz.
Paylaşılan modülde ağ oluşturma
İlk olarak, yanıtı temsil eden bir sınıfa ihtiyacımız var - bu alanlar arka uç tarafından döndürülen json'da bulunur.
kotlinx.serialization.Serializable'ı içe aktar @Serileştirilebilir veri sınıfı XkcdResponse( val img: Dize, val başlığı: Dize, val gün: Int, val ay: Int, val yıl: Int, )
Ardından , bir HTTP istemcisi ile API'yi temsil eden bir sınıf oluşturmamız gerekiyor. json'da bulunan tüm alanları sağlamamış olmamız durumunda, seri hale getiricinin eksik olanları yok sayabilmesi için ignoreUnknownKeys
özelliğini kullanabiliriz. Bu örnek, askıya alınmış bir işlev tarafından temsil edilen yalnızca bir uç noktaya sahiptir. Bu değiştirici, derleyiciye bu işlevin eşzamansız olduğunu söyler. Bunu daha çok platforma özel kodla anlatacağım.
io.ktor.client'i içe aktarın.* io.ktor.client.features.json'u içe aktarın.* io.ktor.client.features.json.serializer'ı içe aktarın.* io.ktor.client.request'i içe aktarın* sınıf XkcdApi { özel val baseUrl = "https://xkcd.com" özel değer httpClient = HttpClient() { install(JsonFeature) { serileştirici = KotlinxSerializer( kotlinx.serialization.json.Json { yoksayUnknownKeys = doğru } ) } } eğlenceyi askıya al fetchLatestComic() = httpClient.get<XkcdResponse>("$baseUrl/info.0.json") }
Ağ katmanımız hazır olduğunda, etki alanı katmanına geçebilir ve yerel veri modelini temsil eden bir sınıf oluşturabiliriz. Bu örnekte, biraz daha alan atladım ve resmin sadece komik başlığını ve URL'sini bıraktım.
veri sınıfı ComicModel( val imageUrl: Dize, val başlığı: Dize )
Bu katmanın son kısmı, bir ağ talebini tetikleyecek ve ardından yanıtı yerel modele eşleyecek bir kullanım senaryosu oluşturmaktır.
sınıf GetLatestComicUseCase(özel değer xkcdApi: XkcdApi) { eğlenceyi askıya al run() = xkcdApi.fetchLatestComic() .let { ComicModel(it.img, it.title) } }
Android için basit kullanıcı arayüzü
androidApp
dizinine geçme zamanı – yerel Android uygulamasının depolandığı yer burasıdır. İlk olarak, burada bulunan diğer build.gradle.kts
dosyasına Android'e özgü bazı bağımlılıklar eklememiz gerekiyor. Yine, aşağıdaki liste yalnızca halihazırda mevcut olanlara eklenmesi gereken bağımlılıkları gösterir. Bu uygulama, Model-View-ViewModel mimarisini (ilk iki satır) ve döndürülen URL'den (ikinci iki satır) komik bir resim yüklemek için Glide'ı kullanacak.

bağımlılıklar { uygulama ("androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0") uygulama ("androidx.lifecycle:lifecycle-livedata-ktx:2.2.0") uygulama ("com.github.bumptech.glide:glide:4.11.0") annotationProcessor("com.github.bumptech.glide:compiler:4.11.0") }
Varsayılan olarak, yeni oluşturulan bir proje MainActivity'yi ve onun düzen dosyası activity_main.xml
içermelidir. Buna bazı görünümler ekleyelim – başlık için bir TextView
ve çizgi romanın kendisi için bir ImageView.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:andro android: android:layout_width="match_parent" android:layout_height="match_parent" android:yerçekimi="merkez" android:oryantasyon="dikey"> <Metin Görünümü android: android:layout_width="wrap_content" android:layout_height="wrap_content"/> <Görüntü Görünümü android: android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout>
Ardından , uygulama durumunun bir temsiline ihtiyacımız olacak - yeni bir çizgi roman yükleniyor, gösteriliyor olabilir veya yükleme sırasında bir hatayla karşılaşabiliriz.
mühürlü sınıf Devlet { nesne Yükleniyor: Durum() sınıf Başarı(val sonuç: ComicModel): State() nesne Hatası: Durum() }
Şimdi önceden oluşturulmuş iş mantığını kullanarak minimal bir ViewModel ekleyelim . Tüm sınıflar içe aktarılabilir. MutableLiveData
gözlemlenebilir bir alandır - görünüm, değişiklikleri gözlemleyecek ve buna göre kendini güncelleyecektir. viewModelScope
, viewmodel'in yaşam döngüsüne bağlı bir eşyordam kapsamıdır - uygulamanın kapatılması durumunda bekleyen görevleri otomatik olarak iptal eder.
class MainViewModel : ViewModel() { özel değer getLatestComicUseCase = GetLatestComicUseCase(XkcdApi()) val comic = MutableLiveData<State<ComicModel>>() eğlenceli fetchComic() { viewModelScope.launch { komik.değer = Durum.Yükleniyor() runCatching { getLatestComicUseCase.run() } .onSuccess { komik.değer = Durum.Success(it) } .onFailure { comic.value = State.Error() } } } }
Son bir şey – MainActivity her şeyi bağlamak için.
class MainActivity : AppCompatActivity(R.layout.activity_main) { özel val viewModel: Tembel { tarafından MainViewModel ViewModelProvider(this).get(MainViewModel::class.java) } eğlenceyi geçersiz kıl onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) viewModel.comic.observe(bu) { ne zaman) { Durum.Yükleniyor -> { findViewById<TextView>(R.id.titleLabel).text = "Yükleniyor" } State.Success -> { findViewById<TextView>(R.id.titleLabel).text = it.result.title Glide.with(bu) .load(it.result.img) .into(findViewById(R.id.image)) } State.Error -> { findViewById<TextView>(R.id.titleLabel).text = "Hata" } } } viewModel.fetchComic() } }
İşte bu, Android uygulaması hazır!
iOS için basit kullanıcı arayüzü
Yukarıdaki her şey Android Studio'da yapıldı, bu yüzden bu kısım için daha kullanışlı hale getirmek için Xcode'a geçelim. Bunu yapmak için sadece Xcode'u açın ve iosApp dizinini seçin – önceden yapılandırılmış bir Xcode projesi içerir. Varsayılan olarak bu proje GUI için SwiftUI kullanıyor, bu yüzden basitlik adına buna bağlı kalalım.
Yapılacak ilk şey, komik verileri almak için temel mantık oluşturmaktır. Tıpkı daha önce olduğu gibi, devleti temsil edecek bir şeye ihtiyacımız var.
enum Devlet { vaka yükleme vaka başarısı(ComicModel) vaka hatası }
Ardından, bir kez daha bir ViewModel hazırlayalım
class ViewModel: ObservableObject { let getLatesteComicUseCase = GetLatestComicUseCase(xkcdApi: XkcdApi()) @Published var comic = State.loading içinde() { self.comic = .loading getLatestComicUseCase.run { fetchedComic, hata if fetchedComic != nil { self.comic = .success(fetchedComic!) } başka { self.comic = .hata } } } }
Ve son olarak, manzara.
Not: Kolaylık sağlamak için, görüntüyü görüntülemek için SwiftUI bileşeni RemoteImage'ı kullandım, tıpkı Android'de Glide kullandığım gibi.
struct ContentView: Görünüm { @ObservedObject private(set) var viewModel: ViewModel var body: bazı Görünüm { komikView() } -- private func comicView() -> bazı Görünüm { viewModel.comic'i değiştir { vaka .loading: dönüş AnyView(Metin("Yükleniyor")) case .result(komik olsun): AnyView'ı döndür(VStack { Metin(komik.başlık) RemoteImage(url: komik.img) }) durum .hatası: dönüş AnyView(Metin("Hata")) } } }
İşte bu kadar, iOS uygulaması da hazır!
Özet
Son olarak, başlıktaki soruyu yanıtlamak için – Kotlin Multiplatform, platformlar arası geliştirmenin geleceği mi? - hepsi ihtiyaçlara bağlıdır. Her iki mobil platform için aynı anda küçük, özdeş bir uygulama oluşturmak istiyorsanız, o zaman muhtemelen olmaz, çünkü her iki platform için de geliştirme konusunda gerekli bilgiye sahip olmanız gerekir.
Uzmanlarımızla bir sonraki uygulamanızı geliştirin
fiyat teklifi alAncak, zaten bir Android ve iOS geliştirici ekibiniz varsa ve en iyi kullanıcı deneyimini sunmak istiyorsanız, geliştirme süresini önemli ölçüde azaltabilir . Verilen örnekte olduğu gibi, paylaşılan bir modül sayesinde uygulama mantığı yalnızca bir kez uygulandı ve kullanıcı arayüzü tamamen platforma özel bir şekilde oluşturuldu. Öyleyse neden denemiyorsun? Gördüğünüz gibi, başlamak kolaydır.
Bir iş perspektifinden platformlar arası geliştirme hakkında merak mı ediyorsunuz? Platformlar Arası Geliştirmenin Avantajları hakkındaki makalemize göz atın.