Enkratno pisanje kode in uporaba na več platformah so bile sanje mnogih razvijalcev programske opreme. Čeprav je to že nekaj časa mogoče, je to vedno prišlo na račun vzdrževalnosti, enostavnosti testiranja ali še huje slabe uporabniške izkušnje.
Razvoj mobilnih aplikacij z uporabo izvornega SDK je verjetno izhodišče za vse razvijalce, ki imajo svoje korenine na področju razvoja namiznih aplikacij. Programski jeziki bi za nekatere postali ovira: če bi nekdo imel izkušnje z razvojem namiznih ali zalednih aplikacij Java, bi se premaknil na podjetje za razvoj mobilnih aplikacij in delo z Androidom bi se počutilo veliko lažje kot začetek uporabe Objective-C od začetka za iOS.
Vedno sem bil skeptičen do razvoja različnih platform. Okvirji, ki temeljijo na JavaScript, kot so Sencha, Cordova, Titanium itd., Se nikoli ne izkažejo za pametno, če je zmogljivost pomembna. Pomanjkanje API-jev in domiselna uporabniška izkušnja sta bila dana tem okvirjem.
Potem pa sem naletel na Xamarin.
V tem članku boste izvedeli, kako lahko Xamarin uporabljate za skupno rabo kode na več platformah, ne da bi pri tem ogrozili kateri koli drugi vidik razvoja mobilnih aplikacij. Članek se bo osredotočil zlasti na Android in iOS, vendar lahko s podobnim pristopom dodate podporo za katero koli drugo platformo, ki jo podpira Xamarin.
Xamarin je razvojna platforma ki vam omogoča, da v C # in .NET napišete medplatformne, a izvorne aplikacije za iOS, Android in Windows Phone.
Xamarin ponuja vezave C # na izvorne API-je za Android in iOS. To vam omogoča uporabo celotnega uporabniškega vmesnika Androida in iOS-a, obvestil, grafike, animacije in drugih funkcij telefona - vse s pomočjo C #.
Vsaki novi izdaji Androida in iOS-a ustreza Xamarin, z novo različico, ki vključuje vezave na njune nove API-je.
Xamarinova vrata .NET vključujejo funkcije, kot so podatkovni tipi, generiki, zbiranje smeti, poizvedbe z vgrajenim jezikom (LINQ), asinhroni vzorci programiranja, delegati in podskupina Windows Communication Foundation (WCF). Knjižnice se upravljajo z zadrževanjem, tako da vključujejo samo referenčne komponente.
Xamarin.Forms je plast nad drugimi vezmi uporabniškega vmesnika in API-jem Windows Phone, ki ponuja knjižnico uporabniškega vmesnika v celoti med različnimi platformami.
Za pisanje aplikacij na več platformah z Xamarinom morajo razvijalci izbrati eno od dveh razpoložljivih vrst projektov:
PCL vam omogoča, da napišete kodo, ki jo lahko delite na več platformah, vendar z eno omejitvijo. Ker niso vsi .NET API-ji na voljo na vseh platformah, ga boste s projektom PCL omejili na izvajanje na platformah, na katere je namenjen.
Spodnja tabela prikazuje, kateri API-ji so na voljo na katerih platformah:
Značilnost | .NET Framework | Aplikacije za Windows Store | Silverlight | Windows Phone | Xamarin |
---|---|---|---|---|---|
Jedro | Y. | Y. | Y. | Y. | Y. |
LINQ | Y. | Y. | Y. | Y. | Y. |
IQueryable | Y. | Y. | Y. | 7,5+ | Y. |
Serializacija | Y. | Y. | Y. | Y. | Y. |
Pripisi podatkov | 4.0.3+ | Y. | Y. | Y. | Y. |
Med postopkom gradnje se PCL zbere v ločene DLL-je in jih Mono med izvajanjem naloži. Med izvajanjem je mogoče zagotoviti različno izvedbo istega vmesnika.
Po drugi strani pa vam skupni projekti omogočajo večji nadzor, saj vam omogočajo pisanje kode, specifične za platformo, za vsako platformo, ki jo želite podpirati. Koda v projektu v skupni rabi lahko vsebuje smernice prevajalnika, ki bodo omogočile ali onemogočile odseke kode, odvisno od tega, kateri aplikacijski projekt uporablja kodo.
V nasprotju s PCL projekt v skupni rabi ne ustvari nobene DLL. Koda je vključena neposredno v končni projekt.
Koda za večkratno uporabo lahko prihrani denar in čas za razvojne skupine. Vendar pa dobro strukturirana koda razvijalcem bistveno olajša življenje. Lepo napisane kode brez napak nihče ne ceni bolj kot razvijalci.
Xamarin sam po sebi zagotavlja mehanizem, ki veliko olajša pisanje kode za več platform.
Razvijalci mobilnih naprav poznajo scenarije, ko morajo isto logiko napisati dvakrat ali več, da lahko podpirajo iOS, Android in druge platforme. Toda pri Xamarinu je, kot je razloženo v prejšnjem poglavju, enostavno ponovno uporabiti kodo, ki je napisana za eno platformo tudi za nekatere druge platforme.
Kje potem nastopi MvvmCross?
MvvmCross, kot je ime že namigovalo, omogoča uporabo vzorca MVVM v aplikacijah Xamarin. Na voljo je s kopico knjižnic, API-jev in pripomočkov, ki so zelo koristni pri razvoju različnih platform.
MvvmCross lahko znatno zmanjša količino vzorčne kode, ki bi jo napisali (včasih večkrat v različnih jezikih) v katerem koli drugem pristopu k razvoju aplikacij.
Skupnost MvvmCross priporoča precej preprost in učinkovit način strukturiranja rešitve MvvmCross:
.Core .UI.Droid .UI.iOS
Glavni projekt v rešitvi MvvmCross je povezan s kodo za večkratno uporabo. Glavni projekt je projekt Xamarin PCL, katerega glavni poudarek je ponovna uporabnost.
Vsaka koda, napisana v jedru, mora biti maksimalno agnostična za platformo. Vsebovati mora le logiko, ki jo je mogoče ponovno uporabiti na vseh platformah. Core projekt ne sme uporabljati nobenega API-ja za Android ali iOS niti dostopati do česar koli posebnega za katero koli platformo.
Plast poslovne logike, podatkovna plast in zaledna komunikacija so popolni kandidati za vključitev v projekt Core. Krmarjenje po hierarhiji pogledov (dejavnosti, fragmenti itd.) Bo doseženo v Jedru.
Pred nadaljevanjem je treba razumeti en vzorec arhitekturnega oblikovanja, ki je ključnega pomena za razumevanje MvvmCrossa in njegovega delovanja. Kot je razvidno iz imena, je MvvmCross močno odvisen od vzorca MVVM.
MVVM je vzorec arhitekturnega oblikovanja, ki olajša ločevanje grafičnega uporabniškega vmesnika od poslovne logike in zalednih podatkov.
Kako se ta vzorec uporablja v MvvmCross?
No, ker želimo doseči visoko uporabnost naše kode, želimo imeti v svojem jedru, ki je projekt PCL, čim več. Ker so pogledi edini del kode, ki se razlikuje od ene platforme do druge, jih ne moremo ponovno uporabiti na različnih platformah. Ta del se izvaja v projektih, povezanih s platformo.
MvvmCross nam daje možnost orkestriranja navigacije po aplikacijah iz jedra z uporabo ViewModels.
Z osnovami in tehničnimi podrobnostmi začnimo, začnimo z Xamarinom z ustvarjanjem našega lastnega projekta MvvmCross Core:
Odprite Xamarin Studio in ustvarite rešitev z imenom ApeeScapeExampleSolution
:
Ker ustvarjamo jedrni projekt, je dobro, da se držimo pravila o poimenovanju. Prepričajte se, da Core
končnica je dodana imenu projekta.
Če želite dobiti podporo za MvvmCross, morate v naš projekt dodati knjižnice MvvmCross. Če dodamo, da lahko v Xamarin Studio uporabimo vgrajeno podporo za NuGet.
Če želite knjižnico dodati, z desno miškino tipko kliknite mapo Paketi in izberite Dodaj pakete… možnost.
V iskalnem polju lahko iščemo MvvmCross, ki bo filtriral rezultate, povezane z MvvmCross, kot je prikazano spodaj:
Klik na Dodaj paket gumb bo dodal v projekt.
Z dodajanjem MvvmCrossa v naš projekt smo pripravljeni napisati našo osnovno kodo.
Določimo naš prvi ViewModel. Če ga želite ustvariti, ustvarite hierarhijo map, kot sledi:
Tu je nekaj o vsaki mapi:
Naš prvi ViewModel se imenuje 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(); }); } } }
Zdaj, ko imamo svoj prvi ViewModel, lahko ustvarimo svoj prvi pogled in stvari povežemo skupaj.
Za prikaz vsebine ViewModel moramo ustvariti uporabniški vmesnik.
Prvi korak k ustvarjanju uporabniškega vmesnika Android je ustvariti projekt Android v trenutni rešitvi. Če želite to narediti, z desno miškino tipko kliknite ime rešitve in izberite Dodaj -> Dodaj nov projekt ... . V čarovniku izberite aplikacijo za Android in poskrbite, da boste projekt poimenovali ApeeScapeExample.UI.Droid
.
Kot smo že opisali, moramo zdaj dodati odvisnosti MvvmCross za Android. Če želite to narediti, sledite istim korakom kot pri Core projektu za dodajanje odvisnosti NuGet.
Po dodajanju odvisnosti MvvmCross morate dodati sklic na naš projekt Core, da bomo lahko uporabili tam napisano kodo. Če želite dodati sklic na projekt PCL, z desno miškino tipko kliknite mapo Reference in izberite Uredi reference ... možnost. Na zavihku Projekti izberite predhodno ustvarjen Core projekt in kliknite V redu.
Naslednji del je lahko nekoliko težavno razumeti.
Zdaj moramo MvvmCrossu povedati, kako naj nastavi našo aplikacijo. Da bi to naredili, moramo ustvariti Setup
razred:
namespace ApeeScapeExample.UI.Droid { public class Setup : MvxAndroidSetup { public Setup(Context context) : base(context) { } protected override IMvxApplication CreateApp() { return new Core.App(); } } }
Kot je razvidno iz predavanja, MvvmCrossu sporočamo, da CreateApp
na podlagi Core.App
izvedba, ki je razred, opredeljen v jedru in prikazan spodaj:
public class App : MvxApplication { public override void Initialize() { RegisterAppStart(new AppStart()); } } public class AppStart : MvxNavigatingObject, IMvxAppStart { public void Start(object hint = null) { ShowViewModel(); } }
V App
razreda ustvarjamo primerek AppStart
, ki bo prikazal naš prvi ViewModel.
Edina preostala stvar je zdaj ustvariti datoteko z postavitvijo Androida, ki jo bo vezal MvvmCross:
EditText
V datoteki postavitve imamo vezave, ki jih MvvmCross samodejno razreši. Za View
ustvarjamo vezavo za lastnost Text, ki bo dvosmerna. Kakršna koli sprememba, ki jo prikliče stran ViewModel, se bo samodejno odrazila v pogledu in obratno.
The [Activity(Label = 'ApeeScapeExample.UI.Droid', Theme = '@style/Theme.AppCompat', MainLauncher = true, Icon = '@mipmap/icon')] public class MainActivity : MvxAppCompatActivity { protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); SetContentView(Resource.Layout.Main); } }
razred lahko dejavnost ali fragment. Za poenostavitev uporabljamo dejavnost, ki naloži dano postavitev:
ContactNameCommand
Za prvi gumb imamo vezavo ukazov, kar pomeni, da ko kliknemo gumb, bo MvvmCross poklical Setup
iz ViewModel.
Za drugi gumb bomo prikazali še en ViewModel.
Ustvarjanje projekta iOS se v resnici ne razlikuje od ustvarjanja projekta Android. Za dodajanje novega projekta morate slediti podobnim korakom, le da tokrat namesto Androida preprosto ustvarite projekt iOS. Poskrbite, da bo pravil o poimenovanju dosleden.
Po dodajanju projekta iOS morate dodati odvisnosti za MvvmCross iOS. Koraki so popolnoma enaki kot za Core in Android (z desno miškino tipko kliknite Reference v vašem projektu iOS in kliknite Dodaj reference ... ).
Zdaj je treba, tako kot pri Androidu, ustvariti public class Setup : MvxIosSetup { public Setup(MvxApplicationDelegate appDelegate, IMvxIosViewPresenter presenter) : base(appDelegate, presenter) { } protected override MvvmCross.Core.ViewModels.IMvxApplication CreateApp() { return new App(); } }
razred, ki bo MvvmCrossu povedal, kako nastaviti našo aplikacijo.
Setup
Upoštevajte, da AppDelegate
razred se zdaj razširi MvxIosSetup in za Android se je razširil MvxAndroidSetup .
Tukaj je dodatek, da moramo spremeniti svoj AppDelegate
razred.
[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(); startup.Start(); Window.MakeKeyAndVisible(); return true; } }
na iOS-u je odgovoren za zagon uporabniškega vmesnika, zato moramo povedati, kako bodo pogledi predstavljeni v iOS-u. Več o voditeljih lahko izveste več tukaj .
NavigateToSecondViewModelCommand
Da bi predstavili svoj VIewModel, moramo ustvariti pogled. V tem primeru ustvarimo ViewController z desnim klikom na projekt in izbiro Dodaj -> Nova datoteka in v razdelku iOS izberite ViewController, ki ga bomo poimenovali FirstViewController.
Xamarin ustvari tri datoteke, v katerih bomo določili, kakšne bodo naše vezave. Za razliko od Androida moramo za iOS svoje povezave opredeliti na drugačen način s pomočjo kode (čeprav lahko to storimo tudi v Androidu, v nekaterih primerih pa je to potrebno).
Kadar je treba krmariti med pogledi, se to izvede prek ViewModel. V ukazu ShowViewModel()
je metoda MvxAppCompatActivity
bo našel ustrezen pogled in se pomaknil do njega.
Kako pa MVVMCross ve, kateri pogled je treba naložiti?
V tem ni nobene čarovnije. Ko ustvarimo pogled za Android (Activity ali Fragment), razširimo enega od osnovnih razredov s parametri tipa (ShowViewMolel
). Ko pokličemo View
, MvvmCross poišče Activity
ki se razteza Fragment
ali VM
razred s parametri tipa public interface IPasswordGeneratorService { string Generate(int length); }
. Zato za isti ViewModel ne smete imeti dveh razredov pogleda.
Ker Xamarin zgolj zagotavlja ovijalnike C # okoli izvornih API-jev, ne zagotavlja nobene oblike vbrizgavanja odvisnosti (DI) ali mehanizma inverzije nadzora (IoC).
Brez vbrizgavanja odvisnosti med izvajanjem ali vbrizgavanja časa ni enostavno ustvariti ohlapno povezanih, ponovno uporabljivih, preizkušljivih in enostavno vzdrževalnih komponent. Ideja o IoC in DI je znana že zelo dolgo; podrobnosti o IoC najdete v številnih spletnih člankih. Več o teh vzorcih lahko izveste pri Uvodni članek Martina Fowlerja .
IoC je na voljo od zgodnjih različic MvvmCrosses in omogoča vbrizgavanje odvisnosti med izvajanjem, ko se aplikacija zažene in kadar koli so potrebne.
Da bi dobili ohlapno povezane komponente, nikoli ne bi smeli zahtevati konkretnih izvedb razredov. Zahteva konkretnih izvedb omejuje možnost spreminjanja vedenja izvedb med izvajanjem (ne morete ga nadomestiti z drugo izvedbo). Težko je preizkusiti te komponente.
Iz tega razloga bomo razglasili vmesnik, za katerega bomo izvedli eno konkretno izvedbo.
public class PasswordGeneratorService : IPasswordGeneratorService { public string Generate(int length) { var valid = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'; var res = new StringBuilder(); var rnd = new Random(); while (0 In izvedba:
IPasswordGenerationService
Naš ViewModel lahko zdaj zahteva primerek vmesnika PasswordGeneratorService
, za katerega smo odgovorni.
Da bi MvvmCross vbrizgal App.cs
izvedbe med izvajanjem, moramo MvvmCrossu povedati, katero izvedbo uporabiti. Če želimo uporabiti eno izvedbo za obe platformi, lahko izvedbe registriramo v public override void Initialize() { RegisterAppStart(new AppStart()); Mvx.LazyConstructAndRegisterSingleton(); }
, po registraciji aplikacije:
LazyConstructAndRegisterSingleton
Zgornji klic statične metode Mvx.RegisterSingleton()
registrira izvedbo, ki jo je treba vbrizgati. Ta metoda registrira ustrezno izvedbo, vendar ne ustvari predmeta.
Predmet se ustvari samo, kadar je potreben, in samo enkrat, saj je registriran kot singleton.
Če želimo takoj ustvariti enokraten objekt, ga lahko dosežemo s klicem Mvx.RegisterType()
.
Obstajajo primeri, ko ne želimo, da bi bili v naši aplikaciji samo enotoni. Naš objekt morda ni varen za nit ali pa obstaja kakšen drug razlog, zakaj želimo vedno imeti nov primerek. V tem primeru MvvmCross ponuja metodo public class DroidPasswodGeneratorService : IPasswordGeneratorService { public string Generate(int length) { return 'DroidPasswordGenerator'; } }
, ki jo lahko uporabimo za registracijo izvedbe na način, da ustvari nov primerek, kadar koli je to potrebno.
Če morate za vsako platformo zagotoviti ločene konkretne izvedbe, lahko to vedno storite v projektih, specifičnih za platformo:
Setup.cs
In registracija naše izvedbe se opravi v protected override void InitializePlatformServices() { base.InitializePlatformServices(); Mvx.LazyConstructAndRegisterSingleton(); }
razred v okviru projekta Droid:
InitializePlatformServices
Po inicializaciji kode PCL bo MvvmCross poklical
|_+_|
in registrirajte izvedbe storitev, specifičnih za našo platformo. Ko registriramo več izvedb posameznih enot, bo MvvmCross uporabil samo nazadnje registrirano izvedbo. Vse druge registracije bodo zavržene.
Z Xamarinom ustvarite aplikacije za več platform
V tem članku ste videli, kako vam Xamarin omogoča skupno rabo kode na različnih platformah in obenem ohranja domači občutek in delovanje aplikacij.
MvvmCross ponuja še eno plast abstrakcije, ki še izboljšuje izkušnjo gradnje medplatformnih aplikacij z Xamarinom. Vzorec MVVM ponuja način za ustvarjanje navigacijskih in uporabniških tokov, ki so skupni vsem platformam, pri čemer je količina kode za platformo, ki jo morate napisati, omejena samo na poglede.
Upam, da vam je ta članek dal razlog, da si ogledate Xamarin, in vas motiviral, da z njim sestavite svojo naslednjo aplikacijo na več platformah.