Сентябрь 2016
Том 31 номер 9
Xamarin - Эффективная кросс-платформенная работа в Xamarin
Кевин Эшли | Сентябрь 2016
Продукты и технологии:
Xamarin, Android, iOS и Windows
В статье рассматриваются:
- дизайнерские аспекты кросс-платформенных приложений, создаваемых в Xamarin;
- специфичный для устройств код и Xamarin;
- доступ к облаку из Xamarin;
- расширения, компоненты и плагины;
- поддержка носимых устройств (wearables);
- компиляция XAML.
Если вы побываете в настоящее время в Кремниевой долине, то заметите, что инвесторы и разработчики в большинстве своем настроены весьма консервативно в отношении используемых технологий. Большинство компаний сначала нанимают разработчика под iOS, затем (если у них есть достаточные средства) разработчика под Android и/или Windows. Однако такой подход крайне неэффективен и ведет к переписыванию больших объемов кода: iOS-разработчики применяют Objective-C, Android-разработчики — Java, а Windows-разработчики — C#. Они редко общаются друг с другом, еще реже обмениваются кодом, и это приводит к появлению приложений, несогласованных между платформами, а значит, и к растрате миллионов долларов на поддержку полностью раздельных ветвей и технологий разработки. Если вам нужна эффективная и согласованная технологическая стратегия, ключом к продуктивной работе является использование кросс-платформенной технологии вроде Xamarin. А с появлением «родных» технологий заблаговременной компиляции (ahead-of-time [AOT] compilation), которые транслируют код, написанный на высокоуровневых языках наподобие C#, в статический код, «родной» для конкретных платформ, модель программирования, где нужны отдельные разработчики под Android, iOS и Windows, уходит в прошлое.
Это новое направление для традиционных приложений, но уже весьма успешное в других областях, например в игровой индустрии. Так, более половины всех трехмерных игр для iOS, Android и Windows создаются в Unity. Создавая игры в Unity, вы в основном пишете код на C# в подмножестве Mono, и это весьма похоже на использование C# с Xamarin. Unity-игры выполняются на более чем 20 платформах, в том числе Windows, Android, iOS, OS X, Xbox, PlayStation и др. Это отличный вариант и в разработке неигровых приложений, поэтому Xamarin предоставляет для него превосходную платформу.
Можно ли тот же подход применить для других приложений — не только для игр? С помощью Xamarin — можно: я использовал его при создании Active Fitness, облачной платформы для фитнеса и соответствующих мобильных приложений с более чем двумя миллионами пользователей по всему миру (activefitness.co). Я начал использовать Xamarin еще на раннем цикле разработки и смог создать кросс-платформенное решение для Windows, iOS и Android на основе облака Microsoft Azure. Могу похвастаться тем, что Active Fitness, показанное на рис. 1, имеет более 90% общего кода в своих «родных» приложениях для iOS, Windows и Android. Это само по себе является выигрышем в продуктивности труда. В дополнение большая часть Xamarin, включая Xamarin.Forms (bit.ly/2a8Yo4g), имеет открытый исходный код; платформа активно поддерживается сообществом, и производительность идентична «родному» коду благодаря поддержке AOT во встраиваемых системах. Более того, Xamarin включается в Visual Studio без дополнительной платы, в том числе в Community Edition.
Рис. 1. Active Fitness в действии; демонстрируются трехмерные карты и богатый UI
Дизайнерские аспекты кросс-платформенных приложений, создаваемых в Xamarin
Несколько лет назад дизайн мобильных приложений был поразительно разным на каждой платформе. Например, приложение iOS по дизайну вообще ничем не напоминало приложение Android или Windows. Этого больше нет. Сегодня большинство современных приложений для Windows, Android и iOS используют похожие концепции и парадигмы дизайна. Что случилось? Microsoft создала язык дизайна Modern, применяемый в приложениях Universal Windows Platform (UWP), Google представила дизайн Material, а Apple ввела более современно выглядящий дизайн ОС. Все эти изменения сделали приложения в iOS, Android и Windows выглядящими и действующими подобно друг другу, упростив задачи разработчикам (рис. 2). Разработчики даже прибегли к иконическим шрифтам (iconic fonts), таким как Font Awesome, которые используют сходные концепции символов для одинаковых действий на разных платформах. Конечно, платформы все еще имеют визуальные отличия, например Windows включает активные плитки (live tiles). Возможно, вас это удивит, но, как только вы создадите кросс-платформенное приложение, эти детали легко добавить.
Рис. 2. Active Fitness в Windows (слева), Android (в середине) и iOS (справа)
При разработке с помощью Xamarin у вас есть возможность создавать красивый UI для каждой платформы непосредственно из Visual Studio. Это подразумевает применение iOS Storyboards, Android XML и Windows XAML с доступом к каждому элементу управления или виджету и огромному количеству пользовательских элементов управления от соответствующих поставщиков. Более того, Xamarin обеспечивает стопроцентный доступ полностью из C# к API для каждой платформы.
С помощью библиотеки Xamarin.Forms, которая предоставляет абстракцию API для создания общего UI, многие концепции дизайна через пользовательские рендеры (custom renderers) Xamarin автоматически транслируются в наборы «родных» для каждой платформы элементов управления; это дает вам возможность адаптировать кросс-платформенный элемент управления в его «родное» представление на каждой платформе. Так что вы получаете выигрыш в производительности от истинно кросс-платформенного приложения плюс неограниченные возможности в настройке!
Одно из колоссальных преимуществ применения Xamarin.Forms заключается в том, что это просто надстройка (add-on) — библиотека, добавляемая вами в проект. В отношении продуктивности труда и управления жизненным циклом приложения она бесценна, поскольку вы можете писать код, не особо зависимый от циклов выпуска версий платформ, которые обычно намного длиннее. Xamarin всегда день в день обеспечивала совместимость с основными выпусками iOS, Android и Windows, а теперь, когда она стала системой с открытым кодом, вы можете при необходимости самостоятельно добавить какой-либо элемент управления в Xamarin.Forms, изучив исходный код из репозитария на GitHub для Xamarin.Forms. Кроме того, Xamarin предлагает практически неограниченные возможности расширения через пользовательские рендеры элементов управления для «родных» платформ. Если у вас уже есть какое-то XAML-приложение, вам повезло, потому что Xamarin.Forms — это просто другой диалект XAML, а если ваше приложение использует Silverlight, UWP или XAML, вы можете легко добавить некий кросс-платформенный компонент в iOS или Android.
Создание средств навигации «основное/подробное представление» в Xamarin
Давайте рассмотрим преимущества использования Xamarin, сосредоточившись на одном примере: типичном приложении в iOS, Android и Windows, содержащем шаблон навигации master-detail (основное/подробное представление) (или «гамбургер»). Это приложение мы возьмем из репозитария примеров для Xamarin с открытым исходным кодом (bit.ly/29Tk9VJ). Если бы вы писали это приложение так, как это традиционно делают разработчики для iOS, Android или Windows, вы получили бы в итоге три проекта (на Objective-C, Java и C#), и вам пришлось бы использовать разные элементы управления для каждого из них: SplitView в Windows и аналогичные шаблоны в iOS и Android. Вместо этого вы можете использовать единственный экземпляр Xamarin.Forms, который возьмет на себя всю трудную работу для всех платформ (рис. 3).
Рис. 3. Проект Xamarin Master-Detail с ориентацией на Android, iOS и Windows
В файле App.cs портируемого (portable) проекта я создаю экземпляр корневой страницы приложения:
public App ()
{
MainPage =
new MasterDetailPageNavigation.
MainPage ();
}
Заметьте, что большая часть кода находится в портируемом проекте, общем для всех операционных систем, и что в Xamarin.Forms можно использовать XAML. Например, XAML на рис. 4 выглядит довольно просто, если вы знакомы с «родным» элементом управления SplitView в UWP.
Рис. 4. Создание страницы «основное/подробное представление» с помощью XAML
<?xml version="1.0" encoding="UTF-8"?>
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="https://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MasterDetailPageNavigation;
assembly=MasterDetailPageNavigation"
x:Class="MasterDetailPageNavigation.MainPage">
<MasterDetailPage.Master>
<local:MasterPage x:Name="masterPage" />
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
<NavigationPage>
<x:Arguments>
<local:ContactsPage />
</x:Arguments>
</NavigationPage>
</MasterDetailPage.Detail>
</MasterDetailPage>
Xamarin обеспечивает высокую гибкость в отношении того, что разработчики могут делать с условной компиляцией и выбором платформы. Следующий код меняет значок основной страницы (master page), если платформой является Windows:
if (Device.OS == TargetPlatform.Windows)
{
Master.Icon = "hamburger.png";
}
Специфичный для устройств код и Xamarin
Пока все неплохо, но действительно ли я могу получить практически полный доступ к физической платформе в своем коде Xamarin? Иначе говоря, могу ли я разграничить код, созданный для разных типов устройств? К счастью, Xamarin — одна из немногих кросс-платформенных технологий, которая поддерживает кодирование под «родную» среду и обеспечивает доступ к API. Аналогично UWP-приложениям, позволяющим разграничивать семейства устройств (смартфоны, планшеты или настольные ПК), Xamarin содержит очень полезный селектор Device.Idiom, как показано на рис. 5.
Рис. 5. Применение Device.Idiom для выбора платформы
switch (Device.Idiom)
{
case TargetIdiom.Phone:
heading.Text += " Phone ";
break;
case TargetIdiom.Tablet:
heading.Text += " Tablet ";
break;
case TargetIdiom.Desktop:
heading.Text += " Desktop ";
break;
default:
heading.Text += " unknown ";
break;
}
На рис. 6 представлен другой очень полезный селектор, Device.OnPlatform, который можно использовать как в отделенном коде (codebehind), так и в XAML для выполнения различных операций в зависимости от целевой ОС.
Рис. 6. Применение Device.OnPlatform к разным целевым платформам
// Device.OnPlatform (Action)
//
var box = new BoxView {
Color = Color.Green,
WidthRequest = Device.OnPlatform (30, 40, 50),
HorizontalOptions = LayoutOptions.Center
};
Device.OnPlatform(
iOS: () =>{
box.Color = box.Color.MultiplyAlpha(0.5);
heading.TextColor = Color.Blue;
},
Android: () =>{
box.Color = box.Color.AddLuminosity(0.3);
heading.TextColor = Color.FromRgb(115, 129, 130);
},
WinPhone: () =>{
box.Color = box.Color.AddLuminosity(0.3);
heading.TextColor = Color.Accent;
},
Default: () =>{
heading.Text = "what platform is this?!" + Device.OS;
}
);
Xamarin добавляет в XAML теги OnPlatform, поддерживающие разные платформы, например:
<Button Text="Start Timer"
Clicked="TimerClicked"
BackgroundColor="Gray"
HorizontalOptions="Center">
<Button.WidthRequest>
<OnPlatform x:TypeArguments="x:Double"
iOS="200"
Android="300"
WinPhone="100" />
</Button.WidthRequest>
</Button>
А как быть, если я хочу адаптировать элемент управления, предоставляемый Xamarin.Forms на конкретной платформе? Я уже упоминал о такой функции Xamarin, как пользовательские рендеры, которые обеспечивают эту возможность. Пользовательские рендеры — это классы, которые можно наследовать от встроенных объектов и которые предоставляют функциональность в специфичных для платформ реализациях. Допустим, я хочу создать свой элемент управления CustomMap:
public class CustomMap : Map
{
public List<CustomPin> CustomPins { get; set; }
}
На «родной» платформе сигнатура моего объекта будет включать следующее:
[assembly:ExportRenderer (typeof(CustomMap),
typeof(CustomMapRenderer))]
Поэтому в Android, iOS и Windows я всегда могу настроить то, как выглядит мой элемент управления Map. Любопытно, что оболочка для элемента управления Xamarin Map обертывает элемент управления Windows Maps в Windows, элемент управления Google Maps в Android и «родной» элемент управления iOS Maps в iOS. Что еще можно адаптировать с помощью пользовательских рендеров? Почти любой элемент управления! Элемент управления Map — довольно сложный пример, но можно адаптировать кнопки, надписи, ползунки или любой элемент управления, доступный в Xamarin.Forms.
Благодаря Xamarin.Forms 2.2 теперь Xamarin включает «родное» встраивание (native embedding), что позволяет добавлять любой «родной» элемент управления в приложение Xamarin.Forms (bit.ly/29IEvxH).
Доступ к облаку из Xamarin
Azure всегда была дружественна к кросс-платформенным решениям, предоставляя разнообразные SDK для многих платформ, в том числе iOS, Android и специализированных кросс-платформенных примеров, а также поддержки для Xamarin. За счет этого мое приложение Active Fitness удалось масштабировать под два миллиона пользователей. Благодаря Azure — ее надежности, поддержке и производительности — пользователи могут отслеживать свои данные при ежедневных пробежках, разминках и выполнении различных спортивных упражнений, и каждую минуту подключаются тысяч устройств. Вы найдете несколько отличных руководств по Xamarin на веб-сайте Azure, которые помогут вам узнать о наиболее подходящих для ваших приложений облачных сервисах Microsoft (bit.ly/2a5kciF). Между тем, я хотел бы отметить несколько распространенных областей, где облако очень полезно для мобильных приложений.
Аутентификация Если вам нужно аутентифицировать или идентифицировать пользователей, то скорее всего в вашем приложении Xamarin понадобятся облачные сервисы (подробнее см. по ссылке bit.ly/29HlDD3).
Добавление всплывающих уведомлений в ваши приложения Всплывающие уведомления (push notifications) не только предоставляют механизм взаимодействия для приложений, но и помогают обновлять специфичные для платформы средства, такие как плитки (подробнее см. по ссылке bit.ly/29HlDD3).
Автономная синхронизация Мобильные приложения при повседневном использовании не всегда находятся в онлайновом режиме, однако данные нужно как-то синхронизировать, даже когда устройство отключается от серверной части. О периодически отсоединяемых наборах данных см. мою статью в «MSDN Magazine» msdn.com/magazine/dn890372, а также краткое руководство по созданию приложений Xamarin на bit.ly/29QkXqT.
Azure Mobile Apps — отличная отправная точка для интеграции многих облачных сервисов, включая хранилище, уведомления и аутентификацию. Обратитесь к учебному пособию на bit.ly/29K3IHi, которое посвящено приложениям Xamarin.
Расширения, компоненты и плагины
Xamarin завоевал популярность и развивался за счет значительной поддержке через компоненты, плагины и расширения. Многие расширения доступны на GitHub или через NuGet. Некоторые библиотеки, например Android Support Libraries, клиентские библиотеки Google Play Services, Facebook SDK и такие библиотеки для создания диаграмм событий, как OxyPlot, поддерживаются Xamarin или ее сообществом. Плагины являются уникальными предложениями, которые позволяют разработчикам обращаться к «родной» функциональности из общего кода. То есть, если вы хотите обратиться к функциональности GPS, вам больше не придется писать код по три раза для каждой платформы — вы просто скачиваете NuGet-пакет и обращаетесь к GPS прямо из общего кода. Некоторые плагины имеют открытый исходный код и поддерживаются их разработчиками. Так, Джеймс Монтемагно (James Montemagno) разработал большое количество плагинов для Xamarin, например Connectivity, Settings, Media и другие (bit.ly/2a2mM7J).
В табл. 1 показано несколько полезных расширений, которые я рекомендую использовать по мере углубления в разработку с помощью Xamarin.
Табл. 1. Расширения Xamarin
Название | Описание | NuGet-ссылка | Документация и исходный код на GitHub |
---|---|---|---|
Battery Status | Собирает информацию об уровне заряда аккумулятора, состоянии зарядки и типе | bit.ly/2a4gbZ6 | bit.ly/2a5Ofqm |
Barcode Scanner | Сканирует и создает штрих-коды с помощью ZXing.NET.Mobile | bit.ly/2a5Ofqm | bit.ly/29QykY9 |
Compass | Позволяет обращаться к направлению компаса на устройстве | bit.ly/2a32UAZ | bit.ly/29KfcKV |
Connectivity | Получает информацию о сетевых подключениях, такую как тип и доступность соединения | bit.ly/29QDplO | bit.ly/2a33PBr |
Cryptography | PCL Crypto предоставляет согласованный, портируемый набор криптографических API | bit.ly/29Qz5AE | bit.ly/29PzwAb |
Device Info | Получает характеристики устройства, например ОС, модель, версия и идентификатор | bit.ly/29PzPeg | bit.ly/29QzSBq |
Device Motion | Обеспечивает доступ к акселерометру, гироскопу, магнитометру и компасу | bit.ly/2a6SzTk | bit.ly/2a35maG |
Embedded Resource | Распаковывает встроенный ресурс для кросс-платформенного использования | bit.ly/29J6Wf3 | bit.ly/29J6z46 |
External Maps | Запускает внешние карты по долготе-широте или по адресу | bit.ly/29KgNR0 | bit.ly/2abuJbI |
File System | PCL Storage предлагает кросс-платформенные API хранилища | bit.ly/29LEOru | bit.ly/28Ju1AB |
Geolocator | Обнаруживает GPS-координаты устройства | bit.ly/2a70ekG | bit.ly/29Tpuvd |
Local Notifications | Показывает локальные уведомления | bit.ly/2arOGYf | bit.ly/29TpSd7 |
Media | Позволяет принимать или выбирать фотоснимки и видеозаписи | bit.ly/2a6rpxi | bit.ly/29TqlMm |
Messaging | Позволяет выдавать телефонный звонок, отправлять SMS или сообщение по электронной почте | bit.ly/2a8Uie5 | bit.ly/29SEdDm |
Permissions | Проверяет и запрашивает разрешения в период выполнения | bit.ly/29Tnvo8 | bit.ly/29S6ZKv |
Akavache key-value store | Асинхронное, постоянное (с записью на диск) хранилище пар «ключ-значение» | bit.ly/29Tou7I | bit.ly/2arPSLf |
Push Notifications | Кросс-платформенные всплывающие уведомления для iOS и Android | bit.ly/29ToDs5 | bit.ly/2aex4CR |
Settings | Простой, согласованный кросс-платформенный API настроек | bit.ly/29ToTXT | bit.ly/2a6tn0Q |
Share | Позволяет легко обмениваться текстом, ссылками или открывать браузер | bit.ly/2aa2R51 | bit.ly/2aa3sUk |
Sockets | TCP- и UDP-слушатели и клиенты плюс групповая рассылка по UDP | bit.ly/1rQIyyR | bit.ly/1y1UHPb |
Text to Speech | Позволяет обращаться к механизму синтеза речи из общего кода | bit.ly/29S7Yud | bit.ly/29MMA3S |
User Dialogs | Поддерживает диалоги в стиле окон сообщений | bit.ly/2aa4dMV | bit.ly/29Tqzkd |
Version Tracking | Отслеживает, какие версии вашего приложения устанавливал пользователь | bit.ly/29S8YhH | bit.ly/2a74lNW |
Например, для проверки сетевых подключений с помощью плагина Connectivity в кросс-платформенном решении достаточно одной строки кода вместо специфичного для платформы кода, который нужно раздельно реализовать в iOS, Android и Windows:
public static bool IsOnline
{
get
{
return Plugin.Connectivity.CrossConnectivity.Current.IsConnected;
}
}
Еще больше плагинов и расширений доступно по ссылке bit.ly/29XZ3VM.
Поддержка устройств: Android Wear, WatchKit и Microsoft Band
Xamarin всегда быстро реагировала на появление любых видов устройств и аппаратных платформ на рыке. Я имел удовольствие работать с группой Microsoft Band, и на конференции Build 2016 мы совместно объявили о некоторой весьма интересной функциональности для Active Fitness, в которое была добавлена поддержка более 50 видов фитнеса, в том числе катание на лыжах, сноуборде и др. Кроме того, Active Fitness теперь поддерживает Android Wear (рис. 7). Если вы устанавливаете Active Fitness на устройство Android, то получаете полную поддержку циферблата часов.
Рис. 7. Циферблат Android Wear для приложения Active Fitness
С помощью Xamarin можно добавлять приложения и поддержку гаджетов и устройств, используя следующее.
- Android Wear: Xamarin включает примеры кода и поддержку, в том числе для создания циферблатов на C#.
- Apple WatchKit: Поддержку Xamarin см. в документации по ссылке bit.ly/29XZ3VM.
- Microsoft Band: Помимо Microsoft Band SDK, существует фантастическая оболочка Microsoft Band для кросс-платформенных приложений на Xamarin; она доступна на GitHub (bit.ly/29WeDli) и через NuGet (bit.ly/29SOoLA).
Производительность и компиляция XAML
Xamarin.Forms использует комбинацию логики в XAML и в отделенном коде. При желании можно использовать только код для создания экземпляров UI-объектов и управления ими. По сути, ничто не мешает вам кодировать большую часть UI, кроме эффективности (декларативная природа XAML делает его очень эффективным в написании и управлении). Но если вы действительно хотите этого, то можете наследовать свой Page от ContentPage и писать всю логику в коде, без XAML, как показано на рис. 8.
Рис. 8. Наследование Page от ContentPage без XAML
class ButtonCodePage : ContentPage
{
int count = 0;
public ButtonCodePage()
{
Button button = new Button
{
Text = String.Format("Tap for click count!")
};
button.Clicked += (sender, args) =>
{
count++;
button.Text =
String.Format("{0} click{1}!", count,
count == 1 ? "" : "s");
};
this.Content = button;
}
}
В данном случае весь ваш UI-код является реально компилируемым C#-кодом. При компиляции XAML используется похожая идея: вы можете сообщить Xamarin заранее скомпилировать весь ваш XAML, что сделает UI-код, содержащийся в XAML-файлах, гораздо быстрее в загрузке и выполнении. Существует несколько существенных преимуществ от компиляции XAML: мгновенная проверка при компиляции, исключение времени на загрузку и создание экземпляров и уменьшение размера исполняемых файлов. Вы можете разрешить компиляцию XAML в сборке:
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace MyApp
или на уровне класса:
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MyPage
Заключение
Разрабатывая в Xamarin, я научился концентрироваться на продуктивности труда и использовать широчайшие возможности сообщества открытого исходного кода Microsoft. Как уже отмечалось, Xamarin очень быстро реагирует на тенденции в мире исходного кода и на появление новых устройств: Android Wear, Apple Watch, Microsoft Band и новейших версий Android, iOS и Windows. Ниже перечислено несколько значимых новых добавлений в Xamarin, которые делают его поистине потрясающей платформой.
- Страницы данных Упрощают связывание с данными и еще больше облегчают создание сложных многостраничных приложений (bit.ly/29SRtLk).
- Localization and Multilingual App Toolkit Полностью поддерживает проекты Xamarin, добавляя соответствующую отраслевым стандартам поддержку XLIFF в ваши проекты (bit.ly/2a5Uzwx).
- Native Control Embedding Сильно упрощает добавление «родных» элементов управления в приложения Xamarin (bit.ly/29IEvxH).
- Эффекты Добавляет в приложения Xamarin специфичные для платформ эффекты (bit.ly/29RDrbD).
Xamarin предлагает мощный и эффективный способ создания кросс-платформенных приложений буквально любой сложности, работающих в iOS, Android и Windows. Теперь можно действительно сосредоточиться на функционале и контенте приложения и создать эффективное приложение, которое будет работать в любой ОС. Как только вы начнете создавать свое первое приложение Xamarin, вы вскоре обнаружите, насколько велико и энергично сообщество кросс-платформенных разработчиков.
Кевин Эшли (Kevin Ashley) — архитектор-идеолог в Microsoft. Соавтор книги «Professional Windows 8 Programming» (Wrox, 2012) и разработчик топовых приложений и игр, из которых самым известным является Active Fitness (activefitness.co). Часто выступает с презентациями технологий на различных мероприятиях, отраслевых выставках и принимает участие в веб-кастах. По роду своей деятельности работает с начинающими компаниями и партнерами, консультируя по дизайну программного обеспечения, стратегии бизнеса, технологиям, архитектуре и разработке. Следите за его блогом на kevinashley.com и в Twitter (@kashleytwit).
Выражаю благодарность за рецензирование статьи эксперту Microsoft Джеймсу Монтемагно (James Montemagno)