Xamarin ile Platformlar Arası Uygulamalar Oluşturma: Bir Android Geliştiricisinin Perspektifi

Yayınlanan: 2022-03-11

Bir kez kod yazmak ve onu birden fazla platformda kullanmak birçok yazılım geliştiricinin hayali olmuştur. Bu, bir süredir mümkün olmasına rağmen, her zaman bakım kolaylığı, test kolaylığı ve daha da kötüsü, kötü kullanıcı deneyimi pahasına geldi.

Yerel SDK'yı kullanarak mobil uygulamalar geliştirmek, kökleri masaüstü uygulama geliştirme alanında olan tüm geliştiriciler için muhtemelen başlangıç ​​noktasıdır. Programlama dilleri bazıları için bir engel haline gelebilir: Birisi Java masaüstü veya arka uç uygulamaları geliştirme konusunda deneyimliyse, bir mobil uygulama geliştirme şirketine geçmek ve Android ile çalışmak, iOS için Objective-C ile sıfırdan başlamaktan çok daha kolay olurdu.

Platformlar arası uygulama geliştirme konusunda her zaman şüpheciydim. Sencha, Cordova, Titanium vb. gibi JavaScript tabanlı çerçeveler, performans önemli olduğunda asla akıllıca bir seçim olmaz. API'lerin eksikliği ve ilginç kullanıcı deneyimi bu çerçevelerle verildi.

Ama sonra Xamarin ile karşılaştım.

Xamarin ile platformlar arası geliştirme

Bu makalede, mobil uygulama geliştirmenin diğer yönlerinden hiçbirinden ödün vermeden birden çok platformda kod paylaşmak için Xamarin'i nasıl kullanabileceğinizi öğreneceksiniz. Makale özellikle Android ve iOS'a odaklanacak, ancak benzer bir yaklaşım kullanarak Xamarin'in desteklediği diğer platformlar için destek ekleyebilirsiniz.

Xamarin Nedir?

Xamarin, iOS, Android ve Windows Phone için C# ve .NET'te platformlar arası, ancak yerel uygulamalar yazmanıza olanak tanıyan bir geliştirme platformudur.

Xamarin, yerel Android ve iOS API'lerine C# bağlamaları sağlar. Bu size tüm Android ve iOS'un yerel kullanıcı arabirimini, bildirimleri, grafikleri, animasyonu ve diğer telefon özelliklerini C# kullanarak kullanma gücü verir.

Android ve iOS'un her yeni sürümü, yeni API'leri için bağlamaları içeren yeni bir sürümle Xamarin tarafından eşleştirilir.

Xamarin'in .NET bağlantı noktası, veri türleri, jenerikler, çöp toplama, dille tümleşik sorgu (LINQ), eşzamansız programlama kalıpları, temsilciler ve Windows Communication Foundation (WCF) alt kümesi gibi özellikleri içerir. Kitaplıklar, yalnızca başvurulan bileşenleri içerecek şekilde oyalanarak yönetilir.

Xamarin.Forms, diğer UI bağlamalarının ve tamamen platformlar arası bir kullanıcı arabirimi kitaplığı sağlayan Windows Phone API'sinin üzerinde bir katmandır.

Xamarin'in kapsamı

Çapraz Platform Uygulamaları Yazma

Xamarin ile platformlar arası uygulamalar yazmak için geliştiricilerin mevcut iki proje türünden birini seçmesi gerekir:

  • Taşınabilir Sınıf Kitaplığı (PCL)
  • Paylaşılan Proje

PCL, birden çok platform arasında paylaşılabilen, ancak bir sınırlamayla kod yazmanıza olanak tanır. Bir PCL projesiyle tüm .NET API'leri tüm platformlarda bulunmadığından, hedeflendiği platformlarda çalışmasını sınırlamış olursunuz.

Xamarin'in bağlantıları ve sınırlamaları

Aşağıdaki tablo, hangi API'lerin hangi platformlarda mevcut olduğunu gösterir:

Özellik .NET Çerçevesi Windows Mağazası Uygulamaları gümüş ışık Windows Telefon Xamarin
Çekirdek Y Y Y Y Y
LINQ Y Y Y Y Y
sorgulanabilir Y Y Y 7.5+ Y
seri hale getirme Y Y Y Y Y
Veri Açıklamaları 4.0.3+ Y Y Y Y

Oluşturma işlemi sırasında, bir PCL ayrı DLL'lerde derlenir ve çalışma zamanı sırasında Mono tarafından yüklenir. Çalışma zamanı sırasında aynı arabirimin farklı bir uygulaması sağlanabilir.

Öte yandan, paylaşılan projeler, desteklemek istediğiniz her platform için platforma özel kod yazmanıza izin vererek size daha fazla kontrol sağlar. Paylaşılan bir projedeki kod, kodu hangi uygulama projesinin kullandığına bağlı olarak kod bölümlerini etkinleştirecek veya devre dışı bırakacak derleyici yönergeleri içerebilir.

Bir PCL'den farklı olarak, paylaşılan bir proje herhangi bir DLL üretmez. Kod doğrudan nihai projeye dahil edilmiştir.

MvvmCross ile Platformlar Arası Kodunuza Yapı Verme

Yeniden kullanılabilir kod, geliştirme ekipleri için paradan ve zamandan tasarruf sağlayabilir. Ancak iyi yapılandırılmış kod, geliştiriciler için hayatı çok daha kolaylaştırır. Hiç kimse, güzel yazılmış hatasız kodu geliştiricilerden daha fazla takdir edemez.

Xamarin tek başına, yeniden kullanılabilir çapraz platform kodu yazmayı çok daha kolay hale getiren bir mekanizma sağlar.

Mobil geliştiriciler, iOS, Android ve diğer platformları desteklemek için aynı mantığı iki veya daha fazla yazmak zorunda oldukları senaryolara aşinadır. Ancak Xamarin ile, bir önceki bölümde açıklandığı gibi, bir platform için yazılmış kodu diğer bazı platformlar için de yeniden kullanmak kolaydır.

O zaman MvvmCross nerede devreye giriyor?

MvvmCross, adından da anlaşılacağı gibi, Xamarin uygulamalarında MVVM desenini kullanmayı mümkün kılar. Platformlar arası uygulama geliştirmede gerçekten kullanışlı olan bir dizi kitaplık, API ve yardımcı programla birlikte gelir.

MvvmCross, uygulama geliştirmeye yönelik diğer herhangi bir yaklaşımda yazacağınız ortak kod (bazen farklı dillerde birden çok kez) miktarını önemli ölçüde azaltabilir.

Bir MvvmCross Çözümünün Yapısı

MvvmCross topluluğu, bir MvvmCross çözümünü yapılandırmanın oldukça basit ve verimli bir yolunu önerir:

 <ProjectName>.Core <ProjectName>.UI.Droid <ProjectName>.UI.iOS

Bir MvvmCross çözümündeki Çekirdek projesi, yeniden kullanılabilir kodla ilgilidir. Core projesi, ana odak noktasının yeniden kullanılabilirlik olduğu bir Xamarin PCL projesidir.

Core'da yazılan herhangi bir kod, mümkün olan en yüksek şekilde platformdan bağımsız olmalıdır. Yalnızca tüm platformlarda yeniden kullanılabilen mantığı içermelidir. Core projesi herhangi bir Android veya iOS API kullanmamalı veya herhangi bir platforma özel herhangi bir şeye erişmemelidir.

İş mantığı katmanı, veri katmanı ve arka uç iletişimi, Core projesine dahil edilmek için mükemmel adaylardır. Görünümler hiyerarşisi (aktiviteler, parçalar, vb.) arasında gezinme, Çekirdek'te sağlanacaktır.

Devam etmeden önce, MvvmCross'u ve nasıl çalıştığını anlamak için çok önemli olan bir mimari tasarım modelini anlamak gerekir. Adından da anlaşılacağı gibi, MvvmCross, büyük ölçüde MVVM modeline bağlıdır.

MVVM, grafik kullanıcı arayüzünün iş mantığı ve arka uç verilerinden ayrılmasını kolaylaştıran bir mimari tasarım modelidir.

Bu kalıp MvvmCross'ta nasıl kullanılır?

Pekala, kodumuzun yüksek yeniden kullanılabilirliğini elde etmek istediğimizden, bir PCL projesi olan Core'umuzda elimizden geldiğince sahip olmak istiyoruz. Görünümler, kodun bir platformdan diğerine farklılık gösteren tek parçası olduğundan, bunları platformlar arasında yeniden kullanamayız. Bu kısım platformla ilgili projelerde uygulanmaktadır.

MvvmÇapraz yapı

MvvmCross, bize ViewModels kullanarak Core'dan uygulama navigasyonunu düzenleme yeteneği verir.

Temel bilgileri ve teknik ayrıntıları ortadan kaldırarak, kendi MvvmCross Core projemizi oluşturarak Xamarin ile başlayalım:

Bir MvvmÇapraz Çekirdek Projesi Oluşturma

Xamarin Studio'yu açın ve ToptalExampleSolution adlı bir çözüm oluşturun:

Çözümü oluşturmak

Bir Core projesi oluşturduğumuz için adlandırma kuralına bağlı kalmak iyi bir fikirdir. Proje adına Core son ekinin eklendiğinden emin olun.

MvvmCross desteği alabilmek için projemize MvvmCross kütüphanelerini eklememiz gerekmektedir. Bunu eklemek için Xamarin Studio'da NuGet için yerleşik desteği kullanabiliriz.

Bir kitaplık eklemek için Paketler klasörüne sağ tıklayın ve Paket Ekle… seçeneğini seçin.

Arama alanında, MvvmCross ile ilgili sonuçları aşağıda gösterildiği gibi filtreleyecek olan MvvmCross'u arayabiliriz:

Sonuçları filtreleme

Paket Ekle butonuna tıklandığında projeye eklenecektir.

Projemize eklenen MvvmCross ile Core kodumuzu yazmaya hazırız.

İlk ViewModel'imizi tanımlayalım. Bir tane oluşturmak için aşağıdaki gibi bir klasör hiyerarşisi oluşturun:

Önerilen klasör hiyerarşisi

İşte her bir klasörün konusu:

  • Modeller: Gerçek durum içeriğini temsil eden etki alanı modelleri
  • Hizmetler: Hizmetimizi içeren bir klasör (iş mantığı, veritabanı vb.)
  • ViewModel: Modellerimizle iletişim kurma şeklimiz

İlk ViewModel'imizin adı FirstViewModel.cs

 public class FirstViewModel : MvxViewModel { private string _firstName; private string _lastName; private string _fullName; public string FirstName { get { return _firstName; } set { _lastName = value; RaisePropertyChanged(); } } public string LastName { get { return _lastName; } set { _lastName = value; RaisePropertyChanged(); } } public string FullName { get { return _fullName; } set { _fullName = value; RaisePropertyChanged(); } } public IMvxCommand ConcatNameCommand { get { return new MvxCommand(() => { FullName = $"{FirstName} {LastName}"; }); } public IMvxCommand NavigateToSecondViewModelCommand { get { return new MvxCommand(() => { ShowViewModel<SecondViewModel>(); }); } } }

Artık ilk ViewModel'imize sahip olduğumuza göre, ilk görünümümüzü oluşturabilir ve nesneleri birbirine bağlayabiliriz.

Android kullanıcı arayüzü

ViewModel'in içeriğini göstermek için bir UI oluşturmamız gerekiyor.

Android kullanıcı arayüzü oluşturmanın ilk adımı, mevcut çözümde bir Android projesi oluşturmaktır. Bunu yapmak için, çözüm adına sağ tıklayın ve Ekle -> Yeni Proje Ekle… öğesini seçin. Sihirbazda Android uygulamasını seçin ve projenize ToptalExample.UI.Droid adını verdiğinizden emin olun.

Daha önce açıklandığı gibi, şimdi Android için MvvmCross bağımlılıkları eklememiz gerekiyor. Bunu yapmak için, NuGet bağımlılıkları eklemek için Core projesiyle aynı adımları izleyin.

MvvmCross bağımlılıklarını ekledikten sonra orada yazılan kodumuzu kullanabilmemiz için Core projemize bir referans eklememiz gerekiyor. PCL projesine bir referans eklemek için Referanslar klasörüne sağ tıklayın ve Referansları Düzenle… seçeneğini seçin. Projeler sekmesinde, önceden oluşturulmuş Çekirdek projeyi seçin ve Tamam'a tıklayın.

PCL projesine referans ekleme

Sonraki kısmı anlamak biraz zor olabilir.

Şimdi MvvmCross'a uygulamamızı nasıl kurması gerektiğini söylemeliyiz. Bunu yapmak için bir Setup sınıfı oluşturmalıyız:

 namespace ToptalExample.UI.Droid { public class Setup : MvxAndroidSetup { public Setup(Context context) : base(context) { } protected override IMvxApplication CreateApp() { return new Core.App(); } } }

Sınıftan da anlaşılacağı gibi, Core'da tanımlanan ve aşağıda gösterilen bir sınıf olan Core.App uygulamasını temel alarak CreateApp söylüyoruz:

 public class App : MvxApplication { public override void Initialize() { RegisterAppStart(new AppStart()); } } public class AppStart : MvxNavigatingObject, IMvxAppStart { public void Start(object hint = null) { ShowViewModel<FirstViewModel>(); } }

App sınıfında, ilk ViewModel'imizi gösterecek olan bir AppStart örneği oluşturuyoruz.

Şimdi geriye kalan tek şey, MvvmCross tarafından bağlanacak bir Android Düzen dosyası oluşturmak:

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:andro xmlns:local="http://schemas.android.com/apk/res-auto" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <EditText android:layout_width="match_parent" android:layout_height="match_parent" local:MvxBind="Text FirstName" /> <EditText android:layout_width="match_parent" android:layout_height="match_parent" local:MvxBind="Text LastName" /> <TextView android:layout_width="match_parent" android:layout_height="match_parent" local:MvxBind="Text FullName" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" local:MvxBind="Click ConcatNameCommand" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" local:MvxBind="Click NavigateToSecondViewModelCommand" /> </LinearLayout>

Düzen dosyasında, MvvmCross tarafından otomatik olarak çözülen bağlamalarımız var. EditText için, Text özelliği için iki yönlü bir bağlama olacak bir bağlama oluşturuyoruz. ViewModel tarafından çağrılan herhangi bir değişiklik, görünüme otomatik olarak yansıyacaktır ve bunun tersi de geçerlidir.

View sınıfı bir aktivite veya bir parça olabilir. Basit olması için, verilen düzeni yükleyen bir aktivite kullanıyoruz:

 [Activity(Label = "ToptalExample.UI.Droid", Theme = "@style/Theme.AppCompat", MainLauncher = true, Icon = "@mipmap/icon")] public class MainActivity : MvxAppCompatActivity<FirstViewModel> { protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); SetContentView(Resource.Layout.Main); } }

İlk düğme için, bir komut bağlamamız var, bu, düğmeye tıkladığımızda ContactNameCommand ViewModel'den ContactNameCommand'ı çağıracağı anlamına geliyor.

İkinci düğme için başka bir ViewModel göstereceğiz.

iOS kullanıcı arayüzü

Bir iOS projesi oluşturmak, bir Android projesi oluşturmaktan gerçekten farklı değildir. Yeni bir proje eklemek için benzer adımları izlemeniz gerekiyor, ancak bu sefer Android yerine bir iOS projesi oluşturmanız yeterli. Adlandırma kuralını tutarlı tuttuğunuzdan emin olun.

iOS projesini ekledikten sonra MvvmCross iOS için bağımlılıklar eklemeniz gerekiyor. Adımlar kesinlikle Core ve Android ile aynıdır (iOS projenizde Referanslar'a sağ tıklayın ve Referans Ekle… 'ye tıklayın).

Şimdi, Android için yaptığımız gibi, MvvmCross'a uygulamamızı nasıl kuracağımızı anlatacak bir Setup sınıfı oluşturmamız gerekiyor.

 public class Setup : MvxIosSetup { public Setup(MvxApplicationDelegate appDelegate, IMvxIosViewPresenter presenter) : base(appDelegate, presenter) { } protected override MvvmCross.Core.ViewModels.IMvxApplication CreateApp() { return new App(); } }

Setup sınıfının artık MvxIosSetup öğesini genişlettiğini ve Android için MvxAndroidSetup öğesini genişlettiğini unutmayın.

Buradaki bir ekleme, AppDelegate sınıfımızı değiştirmemiz gerektiğidir.

AppDelegate , kullanıcı arayüzünü başlatmaktan sorumludur, bu nedenle görünümlerin iOS'ta nasıl sunulacağını söylemeliyiz. Sunucular hakkında daha fazla bilgiyi buradan edinebilirsiniz.

 [Register("AppDelegate")] public class AppDelegate : MvxApplicationDelegate { // class-level declarations public override UIWindow Window { get; set; } public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions) { Window = new UIWindow(UIScreen.MainScreen.Bounds); var presenter = new MvxIosViewPresenter(this, Window); var setup = new Setup(this, presenter); setup.Initialize(); var startup = Mvx.Resolve<IMvxAppStart>(); startup.Start(); Window.MakeKeyAndVisible(); return true; } }

VIewModel'imizi sunmak için bir görünüm oluşturmamız gerekiyor. Bu durumda projeye sağ tıklayıp Add -> New File seçerek bir ViewController oluşturalım ve FirstViewController adını vereceğimiz iOS bölümünden ViewController'ı seçelim.

Xamarin, bağlamalarımızın ne olacağını tanımlayacağımız üç dosya oluşturur. Android'den farklı olarak, iOS için, bağlamalarımızı kod aracılığıyla farklı bir şekilde tanımlamamız gerekir (ancak bunu Android'de de yapabiliriz ve bazı durumlarda bunu yapmak gerekir).

Görünümler arasında gezinmek gerektiğinde, ViewModel aracılığıyla yapılır. NavigateToSecondViewModelCommand komutunda, ShowViewModel<SecondViewModel>() yöntemi uygun görünümü bulur ve ona gider.

Ancak, MVVMCross hangi görünümün yükleneceğini nasıl biliyor?

Bunda bir sihir yok. Android (Activity veya Fragment) için bir görünüm oluşturduğumuzda, temel sınıflardan birini tür parametreleriyle ( MvxAppCompatActivity<VM> ) genişletiyoruz. ShowViewMolel<VM> öğesini çağırdığımızda, MvvmCross, Activity veya Fragment sınıfını VM tür parametreleriyle genişleten bir View arar. Bu nedenle, aynı ViewModel için iki görünüm sınıfına sahip olmanıza izin verilmez.

Kontrolün Tersine Çevirilmesi

Xamarin yalnızca yerel API'ler etrafında C# sarmalayıcıları sağladığından, herhangi bir bağımlılık enjeksiyonu (DI) veya denetimin tersine çevrilmesi (IoC) mekanizması sağlamaz.

Çalışma zamanı bağımlılık enjeksiyonu veya derleme zamanı enjeksiyonu olmadan, gevşek bağlı, yeniden kullanılabilir, test edilebilir ve bakımı kolay bileşenler oluşturmak kolay değildir. IoC ve DI fikri çok uzun zamandır bilinmektedir; IoC ile ilgili ayrıntılar birçok çevrimiçi makalede bulunabilir. Martin Fowler'ın giriş makalesinden bu kalıplar hakkında daha fazla bilgi edinebilirsiniz.

IoC, MvvmCrosses'in ilk sürümlerinden beri mevcuttur ve uygulama başladığında ve gerektiğinde çalışma zamanında bağımlılıkların enjeksiyonuna izin verir.

Gevşek bağlı bileşenler elde etmek için, sınıfların somut uygulamalarına asla ihtiyaç duymamalıyız. Somut uygulamalar gerektirmek, çalışma zamanı sırasında uygulamaların davranışını değiştirme yeteneğini sınırlar (bunu başka bir uygulamayla değiştiremezsiniz). Bu bileşenlerin test edilmesini zorlaştırır.

Bu nedenle, somut bir uygulamaya sahip olacağımız bir arayüz ilan edeceğiz.

 public interface IPasswordGeneratorService { string Generate(int length); }

Ve uygulama:

 public class PasswordGeneratorService : IPasswordGeneratorService { public string Generate(int length) { var val; var res = new StringBuilder(); var rnd = new Random(); while (0 < length--) { res.Append(valid[rnd.Next(valid.Length)]); } return res.ToString(); } }

ViewModel'imiz artık sağlamaktan sorumlu olduğumuz IPasswordGenerationService arabiriminin bir örneğini gerektirebilir.

MvvmCross'un çalışma zamanında bir PasswordGeneratorService uygulamasını enjekte etmesi için, MvvmCross'a hangi uygulamanın kullanılacağını söylememiz gerekir. Her iki platform için bir uygulama kullanmak istiyorsak, uygulama kaydından sonra uygulamaları App.cs :

 public override void Initialize() { RegisterAppStart(new AppStart()); Mvx.LazyConstructAndRegisterSingleton<IPasswordGeneratorService, PasswordGeneratorService>(); }

Statik yönteme yapılan yukarıdaki LazyConstructAndRegisterSingleton<TInterface, TType> enjekte edilecek uygulamayı kaydeder. Bu yöntem, uygun uygulamayı kaydeder ancak bir nesne oluşturmaz.

Nesne, tekil olarak kaydedildiği için yalnızca gerektiğinde ve yalnızca bir kez oluşturulur.

Hemen bir singleton nesnesi oluşturmak istiyorsak, bunu Mvx.RegisterSingleton<TInterface>() çağırarak başarabiliriz.

Uygulamamızda yalnızca singleton'ların olmasını istemediğimiz durumlar var. Nesnemiz iş parçacığı için güvenli olmayabilir veya her zaman yeni bir örneğe sahip olmak istememizin başka bir nedeni olabilir. Durum buysa, MvvmCross, gerektiğinde yeni bir örneği başlatacak şekilde uygulamayı kaydetmek için kullanılabilen Mvx.RegisterType<TInterface,TType>() yöntemini sağlar.

Her platform için ayrı somut uygulamalar sağlamanız gerekirse, platforma özel projelerde bunu her zaman yapabilirsiniz:

 public class DroidPasswodGeneratorService : IPasswordGeneratorService { public string Generate(int length) { return "DroidPasswordGenerator"; } }

Ve uygulamamızın kaydı, Droid projesi altındaki Setup.cs sınıfında yapılır:

 protected override void InitializePlatformServices() { base.InitializePlatformServices(); Mvx.LazyConstructAndRegisterSingleton<IPasswordGeneratorService, DroidPasswodGeneratorService>(); }

PCL kodunun başlatılmasından sonra MvvmCross, InitializePlatformServices arayacak ve platforma özel hizmet uygulamalarımızı kaydedecektir.

Birden çok singleton uygulamasını kaydettiğimizde, MvvmCross yalnızca en son kaydedilen uygulamayı kullanacaktır. Diğer tüm kayıtlar silinecektir.

Xamarin ile Platformlar Arası Uygulamalar Derleyin

Bu makalede, Xamarin'in farklı platformlar arasında kod paylaşmanıza ve yine de uygulamaların yerel hissini ve performansını korumanıza nasıl izin verdiğini gördünüz.

MvvmCross, Xamarin ile platformlar arası uygulamalar oluşturma deneyimini daha da geliştiren başka bir soyutlama katmanı sunar. MVVM modeli, tüm platformlar için ortak olan gezinme ve kullanıcı etkileşimi akışları oluşturmanın bir yolunu sağlayarak, yazmanız gereken platforma özgü kod miktarını yalnızca görünümlerle sınırlı hale getirir.

Umarım bu makale size Xamarin'e bir göz atmak için bir neden vermiştir ve sizi onunla bir sonraki çapraz platform uygulamanızı oluşturmaya motive etmiştir.