Друзья! Мы продолжаем колонку на тему разработки мобильных приложений на Xamarin. И
после небольшого перерыва готовы вернуться к рассмотрению особенностей использования Xamarin.Forms при разработке бизнес-приложений для iOS и Android. Все статьи из колонки можно будет найти и прочитать по ссылке #xamarincolumn
В сегодняшней статье мы рассмотрим вопросы производительности приложений и оптимизации самого процесса разработки.
Правильные пчелы
В замечательной сказке про Винни-Пуха пчелы делились на правильных и неправильных. Аналогично и окружения, в которых будет идти разработка приложений могут быть условно разделены на правильные и неправильные.
Начнем мы с компьютеров, на которых будет идти разработка.
В своей практике в качестве основной среды мы используем Windows 10 и Visual Studio 2015, поэтому столкнулись с тем, что сборка приложений (в первую очередь Android) занимает непозволительно долго времени.
Мы стали выяснять в чем здесь дело и выявили несколько узких мест, замедляющих разработку:
- во время сборки Android-приложений Xamarin может в первый раз выкачивать необходимые исходные коды дополнительных компонентов и складывать их на локальный диск для последующего использования. Здесь ничего поделать нельзя, поэтому просто будьте готовы к тому, что первая сборка может занять у вас минут 10.
- дальше начинается самое интересное: во время сборки Xamarin гененерирует и использует большое количество файлов (до 200 МБ в папках bin и obj, плюс еще целая куча в папке Temp), поэтому сразу забудьте про использование жестких дисков (HDD) на рабочих станциях — чем быстрее будет у вас SSD, тем лучше.
Особо продвинутым можно рекомендовать использование ОЗУ в качестве раздела для хранения проектов и системной Temp-папки — для этого нужно использовать одну из программ класса RAM Disk.Точных измерений при использовании SSD+RAM Disk не производили, но на глаз разница колоссальна.
Итак, считаем, что с правильным окружением мы разобрались.
XAML — зло или благо
Одним из важных механизмов Xamarin.Forms является возможность использования XAML (на базе XML) для описания интерфейса пользователей.
На наш взгляд, это является хорошим решением с точки зрения технологии производства, так как происходит отделение логики от описания интерфейса и сама по себе UI-разработка становится очень похожей на HTML-верстку, даже стили контролов можно задавать в одном месте как с CSS (ликбез по стилям по ссылке), включая небольшой тюнинг для разных платформ (Device.OnPlatform).
Все было бы отлично, если бы не одно большое “НО”, которое характерно для Xamarin.Forms версии 1.х — XAML-файлы интерпретировались на лету, включая создание всех необходимых контролов и их размещение на экране. Из-за этого каждое открытие нового окна со сложной компоновкой происходило дольше, чем хотелось бы.
В версии 2.0 этот недостаток устранили, реализовав предварительную компиляцию XAML. Использовать ее можно как для отдельных страниц и View на XAML, так и для всего проекта целиком.
Включаем компиляцию отдельной XAML-страницы (файл MainPage.xaml.cs, например)
using Xamarin.Forms.Xaml;
...
[XamlCompilation (XamlCompilationOptions.Compile)]
public class MainPage : ContentPage
{
...
}
Активируем компиляцию по всему проекту — добавляем новую строку в конец файла Properties/AssemblyInfo.cs в PCL-проекте:
...
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
Однако в некоторых случаях, особенно при реализации ячеек для ListView, может быть эффективнее описать компоновку для ViewCell/View/Page руками в коде на C# или спуститься на уровень iOS/Android.
Но к ListView мы еще вернемся.
Картинки, иконки и производительность
Первое, с чем сталкиваются начинающие разработчики на Xamarin.Forms — залипания при прокрутке в списках на базе ListView. Чего греха таить, это одно из болезненных мест платформы, отбрасывающее тень на весь остальной функционал, так как списки используются в больших количествах и практически во всех приложениях.
Для начала мы рассмотрим работу с изображениями, так как очень часто это является одной из причин залипаний.
Стандартный компонент для отображения Image хорош, даже поддерживает кеширование, но он мало пригоден при использовании в реальных проектах. Когда год назад мы уперлись в ограничения Image, пришлось сделать свой простенький кешер изображений с автоматическим масштабированием — для отображения в ячейку передавалась уменьшенная версия, так как с большими изображениями списки просто умирали (это не проблема Xamarin.Forms, а вообще любой разработки приложений, но на Xamarin.Forms она была очень острой).
Потом мы перепробовали несколько различных библиотек и в конце концов остановились на превосходном компоненте под названием FFImageLoading.
Он доступен в Nuget () и позволяет решить сразу несколько задач:
- фоновая загрузку изображений с возможностью повтора запросов;
- использование placeholder во время загрузки;
- автоматическое масштабирование изображений до размеров контрола, включая удаление Alpha-канала на Android для еще большей производительности;
- возможность применения трансформаций к изображениям после загрузки (обрезать до круга или другой формы, наложить blur или другой спец. эффект);
- fade-анимация появления изображения после загрузки.
Вот так использовать компонент при разработке на XAML:
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Sample.Pages.MainPage"
xmlns:ffimageloading="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms"
Title="FFImageLoading Demo">
<ContentPage.Content>
<ffimageloading:CachedImage HorizontalOptions="Center" VerticalOptions="Center"
WidthRequest="300" HeightRequest="300"
DownsampleToViewSize="true"
Source = "https://unsplash.it/600/600/?random"
LoadingPlaceholder = "placeholder.png">
</ffimageloading:CachedImage>
</ContentPage.Content>
</ContentPage>
Вот так можно еще немного улучшить работу FFImageLoading (класс AppDelegate.cs для iOS и MainActivity.cs для Android):
var config = new Configuration
{
HttpClient = new HttpClient(new ModernHttpClient.NativeMessageHandler()), //используем быстрые библиотеки для загрузки
FadeAnimationDuration = 250, //ускоряем анимацию появления
};
FFImageLoading.ImageService.Instance.Initialize(config);
Работаем со спискам в Xamarin.Forms
С помощью FFImageLoading мы оптимизировали отображение изображений в списках и теперь можем перейти к следующему шагу.
Первая рекомендация касается механизмов работы ListView. В ранних версиях Xamarin.Forms не поддерживался механизм повторного использования созданных ячеек, что приводило к созданию экземпляров ViewCell каждый раз при необходимости их отображения — это и было первой серьезной причиной залипаний при скроле.
В последних версиях Xamarin.Forms реализован механизм повторного использования созданных ячеек и для его активации необходимо задать свойству CachingStrategy значение ListViewCachingStrategy.RecycleElement.
Реализация в XAML:
<ListView CachingStrategy="RecycleElement">
...
</ListView>
Реализация на C#:
var listView = new ListView(ListViewCachingStrategy.RecycleElement);
После этого созданные экземпляры ViewCell начинают использоваться повторно и к ним просто подключаются (через Binding) необходимые модели данных по мере отображения.
Еще один интересный способ подсказал мой коллега Кирилл — просто останавливать загрузку и отображение картинок во время прокрутки списка. Этот способ также рекомендуют использовать и создатели FFImageLoading.
Для этого необходимо сделать свой рендерер для ListView для каждой платформы и переопределить события прокрутки.
Пример для Android:
_listView.ScrollStateChanged += (object sender, ScrollStateChangedEventArgs scrollArgs) => {
switch (scrollArgs.ScrollState)
{
case ScrollState.Fling:
ImageService.Instance.SetPauseWork(true); // ставим загрузку картинок на паузу
break;
case ScrollState.Idle:
ImageService.Instance.SetPauseWork(false); // возобновляем загрузку картинок
// здесь должен быть ваш код отображения изображений в отображаемых ячейках
ShowMyImage();
break;</p>
}
};
При необходимости вы также можете создать свои реализации ViewCell через механизм Custom Renderer для каждой платформы — такой подход может быть актуален для сложных ячеек с большим количеством встроенных контролов.
Также хорошие результаты при работе с большими объемами данных и сложными ячейками позволяет достичь использование нативных компонентов UICollectionView (для iOS) и RecyclerView (для Android), но это решение можно рекомендовать продвинутым разработчикам.
Пример использования данных классов представлен в библиотеке TwinTechs — обязательно к знакомству, так как там есть видео-ролики с результатами оптимизации.
Итак, на первых порах освоения Xamarin.Forms необходимо уделить особое внимание работе со списками и подходам к повышению производительности. Это позволит не отвлекаться на данные особенности в последующей разработке.
Заключение
В нашей сегодняшней статье мы рассмотрели базовые механизмы оптимизации рабочего окружения и первые шаги к разработке бизнес-приложений на базе Xamarin.Forms.
В следующем материале мы расскажем об использовании иконочных шрифтов в стиле Font Awesome, инструмента Fody для сокращения кода у ViewModel и механизмах ручной отрисовки своих интерфейсных элементов с помощью библиотеки NControlView.
Оставайтесь на связи и добавляйте свои комментарии и вопросы!
Об авторах
Вячеслав Черников — руководитель отдела разработки компании Binwell. В прошлом — один из Nokia Champion и Qt Certified Specialist, в настоящее время — специалист по платформам Xamarin и Azure. В сферу mobile пришел в 2005 году, с 2008 года занимается разработкой мобильных приложений: начинал с Symbian, Maemo, Meego, Windows Mobile, потом перешел на iOS, Android и Windows Phone.
Полезные ссылки
- Анонс бесплатных инструментов Xamarin для разработки кроссплатформенных приложений на С# по ссылке
- Visual Studio 2015 Community, Visual Studio Team Services, Visual Studio Code: бесплатные предложения для разработчиков
- Дополнительные и бесплатные инструменты и службы в программе Visual Studio Dev Essentials
- Лабораторные работы по разработке, тестированию и управлению жизненым циклом ПО для Visual Studio 2015
Поделиться с друзьями
Комментарии (3)
olen
20.06.2016 18:57> И после небольшого перерыва готовы вернуться к рассмотрению особенностей использования Xamarin.Forms при разработке бизнес-приложений для iOS и Android.
> Начнем мы с компьютеров, на которых будет идти разработка.
> В своей практике в качестве основной среды мы используем Windows 10 и Visual Studio 2015
А как в вашей практике происходит сборка под iOS? Нужна Mac OS или есть какие-то другие пути?ad1Dima
20.06.2016 19:55MacOS все ещё нужна.
Хотя VS 2015 вроде научилась собирать девелоперские сборки Obj-C iOS приложений, до Xamarin такое счастье ещё не добралось.
ad1Dima
Подводя итог, XF все еще хорош только для опытных ксамаринщиков, которые понимают нативные дебри целевых платформ.
Как можно не включить переиспользование ячеек по-умолчанию?
Но такими темпами, к третьей версии может получиться неплохой кросс-платформенный фреймворк для новичков.