Разработка пользовательского интерфейса для Android OS основана на основополагающем принципе — использовать как можно меньше элементов! Но в силу разнообразия элементов интерфейса и их комбинаций иногда сложно сказать, какая реализация является наиболее производительной.
В процессе разработки можно выделить несколько групп элементов пользовательского интерфейса, которые различаются по своему назначению. В данной статье речь пойдет об элементах управления, роль которых состоит в том, чтобы расположить контент. Эту группу элементов часто называют контейнерами (в Android API она называется Layouts).
Контейнеры имеют широкое и разнообразное применение. Это разнообразие порождает головную боль выбора — рациональный набор контейнеров. Давайте рассмотрим частный случай этой задачи.
Эксперимент EGO Creative Innovations
Наиболее популярными элементами управления, которые выступают в качестве контейнеров для Android OS, являются LinearLayout и RelativeLayout. Кроме широкого распространения у этих контролов достаточно большая степень взаимозаменяемости, т. е. возможно достаточно безболезненно один контейнер заменить другим. Как известно, основным отличием данных контейнеров является подход к расположению элементов внутри:
- LinearLayout — позиционирование основано на порядке расположения составных компонентов внутри;
- RelativeLayout — необходимо явно указывать относительное расположение элемента.
Для обоснования рационального выбора реализации сравниваемых контейнеров предлагаем использовать следующие критерии:
- время инициализации графической части;
- занимаемое количество виртуальной памяти;
- удобство использования;
Все, кто занимался разработкой пользовательского интерфейса для Android-платформы, согласятся, что использование LinearLayout в большинстве случаев является более удобным в силу простоты расположения элементов внутри по сравнению с RelativeLayout. Но так как удобство использования — это достаточно субъективный критерий и определяется эмпирически, в данной статье этот критерий не будет ключевым в обосновании выбора.
Несмотря на заявленное преимущество использования LinearLayout, на практике достаточно часто возникают случаи, когда необходимо использовать большее количество контейнеров LinearLayout, чем RelativeLayout, для реализации одного и того же интерфейса. И этот факт нередко играет ключевую роль в выборе реализации интерфейса. Ниже представлено сравнение производительности использования предложенных лейаутов с учетом большего количества LinearLayout для реализации пользовательского интерфейса, аналогичного RelativeLayout.
Для возможности сравнения производительности LinearLayout и RelativeLayout по заданным критериям было создано тестовое приложение. Для примера было создано два одинаковых внешне элементарных пользовательских интерфейса, которые различаются реализацией интерфейса с использованием LinearLayout и RelativeLayout соответственно.
Интерфейс первого фрагмента содержит 20 рядов по 20 элементов View, которые расположены в LinearLayout, при этом каждый ряд отдельно размещен в собственном LinearLayout, что привело к размещению 20 «лишних» контейнеров. В общем, в первом фрагменте 22 контейнера и 400 элементов контента.
Интерфейс второго фрагмента аналогично содержит 20 рядов по 20 элементов View, которые расположены в RelativeLayout. И, в отличии от LinearLayout, в данной реализации все View расположились в одном контейнере. Таким образом, во втором фрагменте — два контейнера и 400 элементов контента, что на 20 контейнеров меньше, чем в первом фрагменте.
Данные фрагменты имеют один и тот же класс, но разные ссылки на файл лейаута. В теле перегруженного метода OnCreateView фрагмента помещена логика для определения потраченного времени на инициализацию и используемую приложением виртуальную память.
В приложении отображается количество переходов на каждый фрагмент, а также среднее значение потраченного времени на инициализацию и среднее значение занимаемой приложением памяти.
Переключение между фрагментами осуществляется с помощью драйвера. Основные элементы приложения показаны на рис.
Результаты эксперимента
Ниже представлены результаты, полученные на реальных девайсах.
Мобильное устройство № 1
- Версия Android SDK — Android Marshmallow (6.0)
- Разрешение дисплея — 1280×720
- Диагональ экрана — 5 дюймов
- Процессор — MediaTek MT6735 4 ядра
- RAM — 2 Гб
Мобильное устройство № 2
- Версия Android SDK — Android Nougat (7.0)
- Разрешение дисплея — 1280×800
- Диагональ экрана — 8 дюймов
- Процессор — MediaTek MT8163 4 ядра
- RAM — 2 Гб
Мобильное устройство № 3
- Версия Android SDK — Android Oreo (8.1)
- Разрешение дисплея — 1920×1080
- Диагональ экрана — 5,5 дюйма
- Процессор — Qualcomm Snapdragon 625 8 ядер
- RAM — 4 Гб
Выводы
Как видно из приведенных выше результатов, на всех устройствах время инициализации вью фрагмента с LinearLayout меньше, чем на аналогичном фрагменте с RelativeLayout. Такая же ситуация с занимаемой приложением памятью — фрагмент с LinearLayout занимает меньше оперативной памяти, чем с RelativeLayout.
Несмотря на казавшуюся очевидность преимущества использования RelativeLayout в качестве контейнера, результат оказался противоположным по критериям производительности из-за меньшего количества контейнеров.
Исходя из полученных результатов, можно сделать вывод, что использование LinearLayout в качестве контейнеров со значительным количеством элементов контента является более предпочтительным. А использовать RelativeLayout следует в случаях невозможности применения LinearLayout.
Также стоит отметить, что для простых пользовательских интерфейсов можно пренебречь разницей в производительности и руководствоваться исключительно удобством использования.
Об авторах: Влад Загубинога — разработчик, Янина Ноэль — бренд-стратег, компания EGO Creative Innovations.