Вступление
Когда вы думаете о приложении Xamarin (или любом другом кроссплатформенном), производительность является наиболее важным соображением. Оптимизировать производительность в собственном приложении немного проще, чем в кроссплатформенном приложении, так как сотни блогов, книг и других ресурсов помогут вам на этом пути. Но таких ресурсов меньше, когда речь идет о приложениях, разработанных с помощью кросс-платформенных приложений, таких как Xamarin.
Это сообщение в блоге призвано восполнить этот пробел. Давайте рассмотрим некоторые из лучших методов повышения производительности вашего приложения Xamarin.Forms.
Включите компилятор XAML:
XAML может быть дополнительно скомпилирован непосредственно в промежуточный язык (IL) с помощью компилятора XAML (XAMLC). XAMLC по умолчанию отключен для обеспечения обратной совместимости. Однако его можно включить как на уровне сборки, так и на уровне класса. Для получения дополнительной информации см. Официальную Документацию по компиляции XAML. Всегда включайте компиляцию XAML, если вы ее используете:
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
Включить сжатие макета
Сжатие макета удаляет указанные макеты из визуального дерева в попытке повысить производительность отрисовки страницы. Прирост производительности, который это дает, зависит от сложности страницы, версии используемой ОС и устройства, на котором выполняется приложение. Однако прирост производительности будет заметен на старых устройствах. Для получения дополнительной информации см. Официальную документацию по сжатию макетов:
Используйте быстрые рендереры
Быстрые средства визуализации сокращают инфляцию и затраты на отрисовку элементов управления Xamarin.Forms на Android, выравнивая результирующую иерархию собственных элементов управления. Это дополнительно повышает производительность за счет создания меньшего количества объектов, что, в свою очередь, приводит к менее сложному визуальному дереву и меньшему использованию памяти.
Для получения дополнительной информации см. Официальную документацию по Fast Renderers. Вы также можете найти более подробную информацию в этом блоге Люка Бэтена:
Оптимизация производительности макета
Самый важный аспект оптимизации на уровне макета - это знать, когда какой макет использовать. Как разработчик XAML вы должны знать, как работает каждый из этих макетов и каковы недостатки использования каждого из них.
Общий:
- Макет, способный отображать несколько дочерних элементов, но имеющий только одного дочернего элемента, является расточительным. Например,
StackLayout
с одним дочерним элементом не имеет смысла, поскольку это просто дополнительная нагрузка по сравнению с XAMLC. - Планируете использовать
StaticResources
для уменьшения избыточности кода и значений жесткого кода? Если да, то вы можете сэкономить время, используя стили для повышения производительности, не выполняя несколько поисков одновременно. - Кроме того, не пытайтесь воспроизвести внешний вид определенного макета, используя комбинацию других макетов, так как это приведет к ненужным вычислениям макета, и, в конце концов, это не имеет особого смысла. Например, не пытайтесь воспроизвести
Grid
макет, используя комбинациюStackLayouts
. - Не устанавливайте
VerticalOptions
иHorizontalOptions
макета, если это не требуется. Значения по умолчанию для него, то есть _ 8_ иLayoutOptions.FillAndExpand
, обеспечивают наилучшую оптимизацию макета. - Изменение этих свойств требует затрат и потребляет память, даже если для них установлены значения по умолчанию. Следовательно, если ваше требование выполняется с использованием
Fill/FillAndExpand
, лучше не упоминать об этом во время создания представлений. - По возможности избегайте использования
RelativeLayout
. Это связано со значительными накладными расходами и никогда не рекомендуется. - При использовании
AbsoluteLayout
по возможности избегайте использования свойстваAbsoluteLayout.Autosize
. - Упакуйте свои представления в конструктор, а не
OnAppearing
. - Обойти прозрачность - если вы можете добиться такого же (или достаточно близкого) эффекта с полной непрозрачностью, сделайте это.
- Используйте _15 _ / _ 16_, чтобы избежать блокировки основного потока. А затем покажите конечный результат с помощью
Device.BeginInvokeOnMainThread();
- Раздувайте представления от основного потока, но обязательно добавьте его в визуальное дерево основного потока. Несоблюдение этого правила не приведет к немедленному сбою вашего приложения, а вместо этого приведет к повреждению его состояния. Будьте особенно осторожны, если вы используете
MessagingCenter
в конструкторе своего представления, потому что он не будет маршалировать событие в нужный для вас поток.
Сетка:
- Уменьшите глубину иерархии макетов, указав значения свойств
Margin
, что позволит создавать макеты с меньшим количеством видов-обтекателей. Для получения дополнительной информации ознакомьтесь с документацией Margins and Padding. - При использовании
Grid
постарайтесь, чтобы было как можно меньше строк и столбцов, для которых установлено значениеAuto
, что заставляет механизм выполнять дополнительные вычисления. Вместо этого по возможности используйте строки и столбцы фиксированного размера. - Установите строки и столбцы так, чтобы они занимали пропорциональное пространство с
GridUnitType.Star
.
StackLayout:
- При использовании
StackLayout
убедитесь, что только один дочерний элемент установлен наLayoutOptions.Expands
. Это свойство гарантирует, что указанный дочерний элемент будет занимать самое большое пространство, котороеStackLayout
может ему предоставить. Примечание. Выполнять эти вычисления более одного раза расточительно. - Не вызывайте никакие методы класса
Layout
, так как они приводят к выполнению дорогостоящих вычислений макета. Вместо этого вполне вероятно, что желаемый макет можно получить, задав свойстваTranslationX
иTranslationY
. В качестве альтернативы вы можете создать подкласс классаLayout<View>
для достижения желаемого поведения макета. - Избегайте звонков
Layout()
(и особенноForceLayout()
).
Этикетка:
- Обновляйте
Label
только при необходимости, так как изменение размера метки может привести к перерасчету всего макета экрана. - Не устанавливайте свойство
VerticalTextAlignment
/HorizontalTextAlignment
ярлыка, если это не требуется. - Установите
LineBreakMode
любой метки наNoWrap
, когда это возможно.
Посмотреть список
- Включение
ListView
вScrollView
- очень плохая практика. Всегда избегайте этого. Вместо этого используйте свойстваListView
Header
иFooter
. - Не используйте
TableView
там, где можно использоватьListView
.TableView
s обычно рекомендуются для таких настроек, как пользовательский интерфейс. - По возможности используйте
ListViewCachingStrategy.RecycleElement
. Это не стратегия кэширования по умолчанию. - Используйте
DataTemplate
селекторы для облегчения разнородных представлений в пределах одногоListView
. Не переопределяйтеOnBindingContextChanged
, чтобы обновить и добиться того же эффекта. - Избегайте передачи
IEnumerable<T>
в качестве источника данных вListView
s. Вместо этого попробуйте использоватьIList<T>
, потому чтоIEnumerable<T>
коллекции не поддерживают произвольный доступ. - Вложение
ListView
s - плохая практика. Вместо этого используйте группы внутри одногоListView
. Вложенность явно не поддерживается и нарушит работу вашего приложения. - ОБЯЗАТЕЛЬНО используйте
HasUnevenRows
там, где вListView
есть строки разного размера. Если содержимое ячейки изменяется динамически (возможно, после загрузки из базы данных), обязательно вызовитеForceUpdateSize()
для ячейки. - Избегайте глубоко вложенных иерархий макетов. Используйте
AbsoluteLayout
илиGrid
, чтобы уменьшить вложенность. - Избегайте конкретных
LayoutOptions
, кромеFill
(Fill
- самый дешевый для вычисления).
Навигация
- Всегда ждите методов
PushAsync
иPopAsync
. Невыполнение этого требования вредит как производительности, так и правильности. - Избегайте скрытия / отображения панели навигации.
- Используйте AppCompat backend для Android. Это улучшит как производительность, так и внешний вид приложения.
Изображений
- Изображения на Android не уменьшаются. Всегда помните об этом, поскольку это одна из причин, по которой ваше приложение достигает OOM.
- Если возможно, установите
Image.IsOpaque
наtrue
. - Загружайте изображения из Content вместо Resources.
Карусель
- По возможности избегайте использования
CarouselPage
; вместо этого используйтеCarouselView
вContentPage
. Причина этого в том, чтоCarouselPage
загружает все данные сразу, что снижает производительность на экстремальных уровнях.
MessagingCenter
- Избегайте использования
MessagingCenter
без крайней необходимости. - Передайте
MessagingCenter
либо как статический метод, либо как метод экземпляра, а не как замыкание / лямбда-выражение.
Оптимизировать ресурсы изображений
Отображение ресурсов изображений может значительно увеличить объем памяти, занимаемой приложением. Следовательно, их следует создавать только при необходимости и выпускать, как только они больше не требуются приложению.
Например, если приложение отображает изображение, считывая его данные из потока, убедитесь, что поток создается только тогда, когда он требуется, и убедитесь, что поток освобождается, когда он больше не нужен. Это может быть достигнуто путем создания потока при создании страницы или при возникновении события Page.Appearing
, а затем удаления потока при возникновении события Page.Disappearing
.
При загрузке изображения для отображения с помощью метода ImageSource.FromUri
кэшируйте загруженное изображение, убедившись, что для свойства UriImageSource.CachingEnabled
установлено значение true
. Для получения дополнительной информации см. Документацию по работе с изображениями.
Для получения дополнительной информации ознакомьтесь с полной документацией по оптимизации ресурсов изображений:
Использовать шаблон пользовательского рендерера
Большинство классов отрисовщика предоставляют метод OnElementChanged
, который вызывается при создании настраиваемого элемента управления Xamarin.Forms для визуализации соответствующего собственного элемента управления. Пользовательские классы средства визуализации в каждом классе средства визуализации, зависящего от платформы, затем переопределяют этот метод для создания экземпляра и настройки собственного элемента управления. Метод SetNativeControl
используется для создания экземпляра собственного элемента управления, и этот метод также назначит ссылку на элемент управления свойству Control
.
Однако в некоторых случаях метод OnElementChanged
можно вызывать несколько раз. Следовательно, чтобы предотвратить утечки памяти, которые могут отрицательно повлиять на производительность, необходимо соблюдать осторожность при создании экземпляра нового собственного элемента управления.
Удалите ненужные привязки:
Не используйте привязки для контента, который можно легко установить статически. Нет никаких преимуществ в создании привязок для данных, которые не нужно связывать, потому что привязки являются дополнительными накладными расходами, особенно по сравнению со статическими переменными.
Например, установка Button.Text = "Submit"
имеет меньше накладных расходов, чем привязка Button.Text
к свойству ViewModel string
со значением «Отправить».
Резюме
В этом блоге описаны и обсуждаются методы повышения производительности приложений Xamarin.Forms. В совокупности эти методы могут значительно уменьшить объем работы, выполняемой ЦП, и объем памяти, потребляемой приложением.
Если я что-то пропустил, добавляйте в комментарии. Я обязательно внесу в сообщение все необходимые изменения. Кроме того, если вы обнаружите что-то неправильное в блоге, пожалуйста, исправьте меня в комментариях.
Нажмите эту кнопку, если вам понравился этот пост.
Вы можете связаться со мной в LinkedIn или StackOverflow! Я всегда на связи! :П
Хотите узнать больше? Предлагаю вам проверить это:
Примечание редактора. Heartbeat - это онлайн-публикация и сообщество, созданное авторами и посвященное предоставлению первоклассных образовательных ресурсов для специалистов по науке о данных, машинному обучению и глубокому обучению. Мы стремимся поддерживать и вдохновлять разработчиков и инженеров из всех слоев общества.
Являясь независимой редакцией, Heartbeat спонсируется и публикуется Comet, платформой MLOps, которая позволяет специалистам по данным и группам машинного обучения отслеживать, сравнивать, объяснять и оптимизировать свои эксперименты. Мы платим участникам и не продаем рекламу.
Если вы хотите внести свой вклад, отправляйтесь на наш призыв к участникам. Вы также можете подписаться на наши еженедельные информационные бюллетени (Deep Learning Weekly и Comet Newsletter), присоединиться к нам в » «Slack и подписаться на Comet в Twitter и LinkedIn для получения ресурсов, событий и гораздо больше, что поможет вам быстрее и лучше строить лучшие модели машинного обучения.