Jak jsem zmínil v jednom z předchozích článků, jsem nadšený z příslibu Uno Platform - přinést Univerzální Platformu Windows na všechny platformy. Chtěl jsem s vývojem projektu pomoci přispěním do zdrojového kódu na GitHubu. Protože vím, že začít pracovat na podobně velkém projektu může být náročné, chci se v sérii článků podělit o kroky, které vedly k mému prvnímu Pull Requestu.
V této části se podíváme na základy - vysvětlíme si, jak Uno zapadá do světa multi-platformních frameworků, sestavíme Uno.UI na našem počítači, seznámíme se se zdrojovým kódem a vybereme si issue na které budeme pracovat.
Uno 101
Než začneme přispívat do Uno Platform, musíme pochopit její filosofii. Existuje mnoho multi-platformních frameworků. Dovolím si s klidem v duši ignorovat ty JavaScriptové a budu se soustředit na scénu C#. Začneme pohledem na Xamarin.Forms a Avalonia UI a pak se seznámíme s tím, jak se od nich Uno liší. Xamarin.Forms má svůj vlastní XAML dialekt a ekosystém ovladacích prkvů a nástrojů. Framework na pozadí používá nativní ovladací prvky dané platformy s pomocí systému rendererů. Tato strategie bohužel vede k tomu, že funkcionalita kterou ovladací prvky v XAMLu nabízí je často pouze průnikem toho, co nabízí všechny platformy. Kromě toho, rozdíly v XAML dialektu mohou být matoucí pro vývojáře, kteří přichází z platforem WPF nebo UWP. Komunita Xamarin.Forms je však velmi aktivní a existuje množství knihoven s ovladacími prvky a nástroji, takže pokud potřebujete něco, co Xamarin.Forms zatím neumí, pravděpodobně to najdete na GitHubu. Avalonia UI také má svůj vlastní XAML dialekt postavený na WPF. V případě ovladacích prvků volí úplně opačný přístup než Xamarin.Forms - používá custom rendering kdekoliv je to možné. Přestože to zajistí stejné UI na všech zařízeních, u některých ovladacích prvků pak chybí nativní "feeling" který uživatelé očekávají.
Jak to vidí Uno Platform
Uno Platform zvolila UWP XAML dialekt nejen jako základ, ale s cílem 100% kompatibility - včetně skvělých vlastností jako jsou AdaptiveTriggers
a control templating. Díky kompatibilitě mohou vývojáři vyvíjet proti UWP a využívat všechny nástroje, které Visual Studio nabízí. Na pozadí se používají nativní ovladací prvky dané platformy pro zajištění nativního chování, ale vzhled samotný je plně přizpůsobitelný s cílém poskytnout jednotné UI. Uno ale nekončí u UI. Uvědomuje si i další oblast, která je při vývoji multiplatformních aplikací náročná - API specifická pro platformu (např. práci s hardware). Namísto toho, aby vývojář musel psát platformně závislý kód, může použít "nativní" Windows API jako je Geolocator
, Launcher
a další, která jsou implementována v Uno Platform a na pozadí volají nativní API cílové platformy. Skvělé na tom je, že jakmile znáte UWP, můžete napsat hodně kódu bez toho, abyste museli přemýšlet nad rozdíly mezi platformami a platformně zavislý kód psát pouze pro API která Uno zatím nepodporuje.
Vytvoření Uno aplikace
Vytvořme si nový projekt pomocí Uno Platform. Nejprve musíme nainstalovat do Visual Studia rozšíření Uno Platform Solution Templates přes menu Tools - Extensions and Updates (VS 2017) nebo Extensions - Manage Extensions (VS 2019).
Poté, co máme rozšíření nainstalované, klikneme na File - New Project a vybereme šablonu Cross-Platform Uno App:
Výsledkem je řešení s několika projekty pro cílové platformy a jeden sdílený projekt který všechny referencují. Platformní projekty obsahují pouze minimum nutné pro funkgování aplikace a aplikační logika a UI patří do Shared projektu:
Ve sdíleném projektu najdeme soubory App.xaml
a MainPage.xaml
, které bychom obvykle očekávali v nové UWP aplikaci. Shared projects jsou vlastně takové "balíčky souborů", které jsou při kompilaci přidány do projektu, který je referencuje. Nejde o referenci jako v případě DLL knihoven a Shared projekt tak nemůže fungovat sám o sobě. API, která může používat jsou určena projektem, který jej referencuje. Projekty pro Android, iOS a WASM všechny referencují NuGet balíček Uno.UI
, který poskytuje jmenné prostory Windows
včetně ovladacích prvků a vlastních implementací mnoha UWP API. UWP projekt se od ostatních trochu liší - neobsahuje žádnou referenci na Uno.UI . Jednoduchým důvodem je fakt, že to není třeba - UWP již zahrnuje jmenný prostor Windows
, takže všehny odkazy v Shared projektu automaticky budou využívat nativní implementaci UWP API. Díky tomu nejsme nikdy omezováni - pokud v Uno nějaká funkčnost zatím chybí, UWP projekt bude přesto fungovat na 100 %. Navíc můžeme nejprve vyvíjet proti UWP projektu a používat všechn nejnovější nástroje které Visual Studio nabízí včetně Designeru, XAML Live Edit & Continue, atd.
Sestavení Uno.UI
Pojďme se teď podívat na zdrojový kód Uno platform. Začneme vytvořením forku Uno repository a naklonováním na disk. Prvním krokem je sestavení samotného Uno.UI řešení. Pro to musíme nejprve mít ve Visual Studiu nainstalované všechny potřebné workloady a SDK. Naštěstí je vše potřebné popsáno v dokumentaci Una, takže můžete postupovat podle uvedených instrukcí. V mém případě sestavení řešení na první pokus neprošlo a musel jsem nejprve samostatně sestavit projekt Uno.UI.BindingHelper.Android a pak znovu celé řešení. Pokud narazíte na jiné problémy, určitě se neváhejte zeptat na Uno Platform Gitteru - tým je velmi přátelský a odpovídá rychle!
Abychom otestovali, že vše funguje správně, spustíme si SamplesApp. Najdeme zde projekt pro každou podporovanou platformu a jeden Shared projekt. Doporučuji spustit Android nebo iOS variantu, protože mají nejširší podporu API po UWP, které ale používá přímo nativní UWP API, takže není zrovna nejlepším příkladem pro testování vašeho vývojového prostředí.
Průvodce zdrojovým kódem
Můžeme začít obecným pohledem na celé řešení. Zde je screenhot jeho hlavních složek:
Podívejme se na každou složku zvlášť:
_Build - obsahuje projekt Uno.UI.Build se skripty,
nuspec
a dalšími zdroji které se využívají pro sestavení UnaAddins - nyní obsahuje projekt Uno.UI.Lottie který obsahuje experimentální podporu pro Lottie animace
SamplesApp - ukázková aplikace pro všechny podporované platformy (zároveň slouží pro UI testy)
SolutionTemplate - šablona pro File -> New Project kterou získáte instalací rozšíření Uno pro Visual Studio
Tools - různé nástroje a generátory
Uno.UI - hlavní projekty Una, včetně Uno a Uno.UI které obsahují většinu logiky
Uno.Xaml - implementace XAMLu která odpovídá UWP XAMLu
Možná jste si všimli, že zde nenajdeme soro žádné "platformně-specifické" projekty - máme to pouze Uno a Uno.UI. Jak to celé tedy funguje? Uno používá multi-targeting. Když otevřeme
Uno.csproj
, uvidíme následující:
Element <TargetFrameworks>
obsahuje výčet platform které Uno podporuje. V csproj
jsou některé výchozí reference které jsou společné pro všechny frameworky, ale pak zde najdeme i platformně-závislé reference:
V této ukázce zjišťuje Condition
attribut, aby uvedené reference byly kompilovány pouze proti platformě MonoAndroid80
. A co se zdrojovým kódem? Můžeme si povšimnou dalšího zajímavého elementu v .csproj
:
Tento soubor props
definuje kompilační konstanty pro jednotlivé platformy:
Jednodušší API mohou být implementovány s jejich pomocí. Skvělým příkladem je Windows.System.Launcher
:
Na základě konstanty je vykonán správný platformně-specifický kód. Uno.CrossTargetting.props
také referencuje další soubor PlatformItemGroups.props
, který zajišťuje, že pro konkrétní cílové platformy budou pro kompilaci zahrnuta pouze podmnožina souborů se zdrojovým kódem pomocí speciálních sufixů v názvu souboru:
Příkladem může být API Windows.Graphics.Display.BrightnessOverride
jehož implementace se skládá z následujících souborů:
- BrightnessOverride.cs - logika společná pro všechny platformy
- BrightnessOverride.iOS.cs - implementace pro iOS
- BrightnessOverride.Android.cs - implementace pro Android
- BrightnessOverride.wasm.cs - implementace pro WASM
Výběr issue
V sekci Issues v repozitáři Uno.UI najdeme vždy množství aktivních bugů, návrhů nových funkcí a vylepšení. Pokud si nejste jistí obtížností konkrétní issue, můžete se vždy zeptat na Gitteru a tým Una vám nějakou úlohu doporučí. Já získal tip na svoji první issue od samotného architekta Una Jérôme Labana, a můžete ji najít zde.
Shrnutí
V této části našeho prvního dobrodružství Unem jsme si prošli vše podstatné do začátku. Nyní máme lepší představu jak do sebe vše zapadá a máme vybranou issue. V dalším článku se budu soustředit na to, jak jsem postupoval při implementaci vlastností třídy DisplayInformation
pro iOS a Android.