Вступление
Независимо от того, насколько инновационным и полезным будет ваше Android-приложение, если оно запаздывает, склонно к зависанию или перегружает память, никто не захочет его использовать.
Производительность очень важна, но это также то, о чем легко забыть, когда вы заняты последними штрихами в своем прекрасном пользовательском интерфейсе или придумываете новые захватывающие функции для вашего приложения.
То есть, пока не начнут появляться негативные отзывы в Google Play.
В этой статье вы получите краткий курс по распространенным проблемам производительности, о которых должен знать каждый разработчик Android. Вы узнаете, как проверить, возникают ли эти проблемы в ваших собственных проектах, с помощью инструментов, предоставляемых Android SDK, плюс один инструмент, уже установленный на вашем устройстве Android.
Если вы обнаружите проблему с производительностью в своем приложении, очевидно, вы захотите ее исправить. Поэтому по пути мы также рассмотрим, как использовать инструменты Android SDK для сбора дополнительной информации о любых проблемах с производительностью, которые вы обнаружите. Получив эту информацию, вы лучше поймете, как улучшить производительность вашего приложения и в конечном итоге создать приложение, которое люди будут любить использовать.
1. Overdraw
Шаг 1: проблема
Пользовательский интерфейс вашего приложения — это ваше соединение с пользователем, но создание чего-то, что выглядит красиво, — это только полдела. Вы также должны убедиться, что ваш пользовательский интерфейс отображается быстро и работает без сбоев.
Одной из наиболее распространенных причин неактивного пользовательского интерфейса является перерисовка . Overdraw — это то, где вы тратите время на обработку GPU, окрашивая пиксели, которые окрашиваются только чем-то другим.
Например, представьте синий фон с текстом на нем. Android не просто рисует области синего цвета, которые видны пользователю, он рисует весь синий фон, а затем рисует текст сверху. Это означает, что некоторые пиксели окрашены в два раза, что является перерисовкой.
Некоторый овердрейт, как в примере выше, неизбежен. Слишком большая перерасход, однако, может оказать заметное влияние на производительность вашего приложения, поэтому вы захотите минимизировать перерасход, где это возможно.
Относительно легко проверить ваше приложение на оверрейт. Большое количество перерисовок может указывать на основную проблему с пользовательским интерфейсом вашего приложения, такую как избыточные представления — подробнее об этом позже. По этим причинам, когда вы тестируете свое приложение на предмет проблем с производительностью, рекомендуется начать с overdraw.
Шаг 2: Обнаружение Overdraw
Хорошая новость заключается в том, что ваше Android-устройство уже имеет встроенную функцию, которая позволяет вам проверять размер перерасхода в любом приложении, установленном на вашем устройстве.
Поскольку эта функция работает на вашем устройстве, первым шагом является установка приложения, которое вы хотите протестировать, на вашем устройстве Android. Затем, чтобы проверить величину перерасхода, просто откройте « Настройки устройства», выберите « Параметры разработчика» и нажмите « Отладка перегрузки графического процессора», а затем « Показать области перерасчета » .
Этот инструмент использует цветные блоки, чтобы выделить различные суммы перерасхода. Осталось только запустить приложение, которое вы хотите протестировать, и посмотреть, какова ситуация с перерисовкой.
- Нет цвета: нет перерасхода. Это означает, что пиксель был нарисован только один раз.
- Синий: перерасход 1х. Пиксель был нарисован дважды.
- Зеленый. Перерасход в 2 раза. Этот пиксель был нарисован три раза. Как правило, вы должны стремиться к максимальному овердрафту в 2 раза.
- Светло-красный: перерасход в 3 раза. В зависимости от вашего приложения, небольшие участки светло-красного цвета могут быть неизбежны, но если вы видите средние или большие участки красного цвета, то вам следует выяснить, что вызывает слишком большой избыток.
- Темно-красный: Перерасход в 4 раза. Этот пиксель был нарисован 5 раз или, возможно, даже больше. Вы определенно захотите выяснить, что вызывает любые темно-красные области.
Шаг 3: Минимизация оверрейда
После того как вы определили область значительного перерасхода, самый простой способ уменьшить это — открыть XML-файлы вашего приложения и найти любые области перекрытия, в частности, какие-либо элементы рисования, которые не видны пользователю, и любые фоны, которые являются рисуются друг на друга.
Вам также следует искать области, где атрибут background установлен на белый цвет, даже если родитель уже закрасил белый фон. Все эти вещи могут привести к значительному перерасходу.
Система Android может автоматически уменьшать простые случаи перерасхода, но стоит отметить, что это не распространяется на сложные пользовательские представления, где Android не имеет представления о том, как вы рисуете свой контент.
Если вы используете сложные пользовательские представления в своем приложении, то вы можете определить границы clipRect
для ваших представлений, используя метод clipRect
. Для получения дополнительной информации, я рекомендую посетить официальную документацию по Android .
2. Android рендеринг конвейер
Шаг 1: проблема
Другой распространенной причиной проблем с производительностью является иерархия представления вашего приложения. Для рендеринга каждого представления Android проходит три этапа:
- мера
- расположение
- привлечь
Время, которое требуется Android для выполнения этих этапов, пропорционально количеству просмотров в вашей иерархии. Это означает, что одним из самых простых способов снизить скорость рендеринга вашего приложения является выявление и удаление любых представлений, которые не влияют на конечное изображение, которое пользователь видит на своем устройстве.
Даже если необходимы все представления в вашей иерархии, способ их размещения может оказать существенное влияние на фазу измерения процесса рендеринга. Вообще говоря, чем глубже ваша иерархия представлений, тем больше времени требуется для завершения фазы измерения.
В процессе рендеринга каждое представление предоставляет свои размеры родительскому представлению. Если родительское представление обнаруживает проблему с любым из этих измерений, оно может вынудить каждого ребенка к повторному измерению.
Измерения могут даже произойти, когда нет ошибки. Например, относительные схемы часто должны измерять их детей дважды, чтобы привести все в соответствие. Линейные макеты с layout_weight
которые используют параметр layout_weight
обычно измеряют каждого дочернего layout_weight
дважды.
В зависимости от того, как устроены ваши представления, измерения и измерения могут быть дорогостоящим, длительным процессом, который оказывает заметное влияние на скорость рендеринга вашего приложения.
Ключ к тому, чтобы ваш пользовательский интерфейс отображался быстро и плавно, — это удаление ненужных представлений и поиск возможностей для выравнивания вашего макета.
Android SDK включает в себя инструмент Hierarchy Viewer , который позволяет визуализировать всю иерархию представлений. Этот инструмент поможет вам определить как избыточные представления, так и вложенные макеты.
Шаг 2. Использование средства просмотра иерархии
Прежде чем мы ближе познакомимся с инструментом просмотра иерархии , есть несколько причуд, о которых нужно знать. Во-первых, средство просмотра иерархии может взаимодействовать только с работающим приложением, а не с исходным кодом вашего приложения. Это означает, что вам нужно установить приложение, которое вы хотите протестировать, на устройстве Android или использовать эмулятор.
Но есть и другая, более значительная выгода. По умолчанию средство просмотра иерархии может взаимодействовать только с устройством, на котором установлена версия операционной системы Android для разработки. Если у вас нет устройства разработчика, вы можете обойти это ограничение, добавив в ViewServer
класс ViewServer
.
Когда вы будете готовы к просмотру Hierarchy Viewer, запустите Android Studio и выберите « Инструменты» на панели инструментов, а затем Android и Android Device Monitor .
Нажмите кнопку Hierarchy View справа, как показано на скриншоте ниже.
В левой части экрана находится вкладка Windows, в которой перечислены все обнаруженные устройства Android и эмуляторы. Выберите ваше устройство, и вы увидите список процессов, запущенных на этом устройстве. Выберите процесс, который вы хотите рассмотреть более подробно, и три области просмотра иерархии обновятся автоматически.
Эти три окна предоставляют три различных визуальных представления иерархии представления:
- В виде дерева: Вид с высоты птичьего полета вашей иерархии представлений, где каждый узел представляет один вид.
- Обзор дерева: представление карты вашей иерархии представлений. Этот вид особенно полезен для определения возможностей выравнивания макета.
- Layout View: блочное представление вашей иерархии представлений.
Эти три окна связаны между собой. Если вы выберете вид в одном окне, он будет выделен в двух других. Вы можете использовать все три окна одновременно, чтобы выследить любые избыточные представления, скрывающиеся в иерархии представлений.
Если вы не уверены, действительно ли представление вносит какой-либо вклад в конечное изображение, просто перейдите в представление дерева и щелкните по нужному узлу. Вы увидите предварительный просмотр того, как это представление будет отображаться на экране, чтобы вы могли точно увидеть, что именно это представление вносит в ваше приложение.
Но только то, что представление вносит вклад в окончательное визуализированное изображение, не означает, что оно также не способствует большой проблеме производительности. Вы уже видели, как вы можете использовать Hierarchy Viewer для выявления очевидных вложенных макетов, но что, если это снижение производительности не столь очевидно? Или что, если что-то еще вызывает медленное рендеринг вида?
Хорошей новостью является то, что вы также можете использовать Hierarchy Viewer, чтобы профилировать, сколько времени требуется каждому представлению, чтобы пройти через различные фазы процесса рендеринга. Это дает вам возможность сосредоточиться на проблемах рендеринга, которые могут быть не очевидны на первый взгляд.
В следующем разделе показано, как использовать Hierarchy Viewer для профилирования различных представлений в макете, чтобы обнаружить любые проблемы с рендерингом, которые могут скрываться под поверхностью.
Шаг 3: Профилирование на узел
Самый простой способ выявить узкие места в вашем пользовательском интерфейсе — собрать данные о том, сколько времени требуется каждому из ваших представлений для завершения этапов измерения, макета и рисования в процессе рендеринга.
Вы можете не только использовать Hierarchy Viewer для сбора этой информации, но и Hierarchy Viewer также отображает эти данные в понятном и наглядном виде, чтобы вы могли сразу увидеть, какие представления работают неэффективно.
Средство просмотра иерархии не отображает время рендеринга по умолчанию. Вы можете добавить эту информацию, перейдя в просмотр дерева и выбрав корневой узел той части дерева, которую вы хотите проверить. Затем вызовите функцию профилирования средства просмотра иерархии, щелкнув зеленый, красный и фиолетовый значок диаграммы Венна, как показано на снимке экрана ниже.
Три цветные точки появятся на каждом узле в этой части иерархии. Слева направо, эти точки представляют:
- время, необходимое для измерения зрения
- время, необходимое для разметки вида
- время, которое требуется, чтобы нарисовать вид
Каждая точка также имеет назначенный цвет:
- Зеленый: для этой части времени рендеринга это представление быстрее, чем по крайней мере половина профилированных узлов. Например, зеленая точка в позиции макета означает, что это представление имеет более быстрый расположение время, по крайней мере, 50% профилированных узлов.
- Желтый: для этой части времени рендеринга это представление находится в самой медленной 50% всех профилированных узлов.
- Красный: для этой части времени рендеринга это представление является самым медленным из всех профилированных узлов.
После сбора этих данных вы не только узнаете, какие представления необходимо оптимизировать, но и точно узнаете, какая часть процесса рендеринга вызывает более медленное рендеринг этого представления.
Просто имейте в виду, что хотя представления с желтыми и красными точками могут быть логическим местом для начала ваших усилий по оптимизации, эти показатели производительности являются относительными для других профилированных узлов в иерархии представления. Другими словами, у вас всегда будут некоторые представления, которые отображаются медленнее, чем другие.
Прежде чем приступить к поиску в коде способов оптимизации конкретного представления, спросите себя, есть ли у этого представления веская причина для рендеринга медленнее, чем у других профилированных узлов, или же это действительно возможность сократить время рендеринга вашего приложения.
3. Утечки памяти
Шаг 1: проблема
Хотя Android — это среда, управляемая памятью, не позволяйте этому ввести вас в заблуждение, поскольку утечки памяти все же могут происходить. Это связано с тем, что сборщик мусора (GC) может удалять только те объекты, которые он распознает как недоступные. Если он не обнаружит недоступный объект, то этот объект не будет собирать мусор.
Эти недоступные объекты слоняются поблизости, загрязняя вашу кучу и занимая ценное пространство. Поскольку ваше приложение продолжает пропускать объекты, объем используемого пространства становится все меньше и меньше, что, в свою очередь, вызывает более частые и продолжительные события GC.
Это плохие новости по двум причинам. Во-первых, хотя события GC обычно не оказывают заметного влияния на производительность вашего приложения, большое количество событий GC, происходящих в течение небольшого промежутка времени, может привести к запаздывающему, не отвечающему пользовательскому интерфейсу. Вторая проблема заключается в том, что на мобильных устройствах изначально не хватает памяти, поэтому утечка памяти может быстро перерасти в OutOfMemoryError, что приведет к сбою приложения.
Утечки памяти могут быть трудно обнаружить. Вы можете осознавать, что память является проблемой для вашего приложения, когда пользователи начинают жаловаться. К счастью, в Android SDK есть несколько полезных инструментов, которые вы можете использовать, чтобы отыскивать свое приложение на предмет этих иногда незаметных признаков утечек памяти.
Шаг 2: Монитор памяти
Монитор памяти — это простой способ получить представление об использовании памяти вашим приложением с течением времени. Обратите внимание, что этот инструмент может подключаться только к работающему приложению, поэтому убедитесь, что приложение, которое вы хотите протестировать, установлено на вашем устройстве Android и ваше устройство подключено к вашему компьютеру.
Этот инструмент встроен в Android Studio, поэтому вы можете получить к нему доступ, щелкнув вкладку « Память » в нижней части вашей IDE. Как только Memory Monitor обнаруживает ваше работающее приложение, он начинает записывать использование памяти вашим приложением.
Если монитор памяти не начинает запись, дважды проверьте, выбрано ли ваше устройство в раскрывающемся меню устройств.
Если монитор памяти возвращает сообщение « Нет приложений для отладки» , откройте меню « Инструменты» в Android Studio, выберите « Android» и убедитесь, что выбран параметр « Включить интеграцию с adb» . Эта функция может быть темпераментной, поэтому вам может потребоваться несколько раз включить или отключить включение интеграции ADB . Это также может помочь удалить ваше устройство Android, а затем снова подключить его.
Как только Memory Monitor обнаружит ваше работающее приложение, он отобразит объем памяти, используемый вашим приложением, синим цветом, а нераспределенная память — голубым.
Потратьте некоторое время на взаимодействие с устройством, следя за тем, как меняется использование памяти вашим приложением в Memory Monitor. В конце концов, выделенная память будет расти, пока не останется свободной памяти. В этот момент система освободит память, вызвав событие GC. Всякий раз, когда вы видите значительное сокращение выделенной памяти, это признак того, что произошло событие GC.
События GC совершенно нормальны, но имейте в виду, если вы видите, что ваше приложение выделяет много памяти за короткий промежуток времени, или события GC становятся более частыми. Это оба явные признаки того, что в вашем приложении происходит утечка памяти.
Если вы используете монитор памяти для отслеживания предполагаемой утечки памяти в течение значительного периода времени, вы можете увидеть, как система Android компенсирует растущие требования к памяти вашего приложения, предоставляя вашему приложению более высокий потолок памяти, после чего цикл начинается снова.
В конце концов, вы можете даже увидеть, что ваше приложение потребляет так много памяти, что система больше не может выделить больше памяти для вашего приложения. Если вы видите, что это происходит, значит что-то серьезно не так с тем, как ваше приложение использует память.
Шаг 3: Монитор устройства Android
Другим инструментом, который может помочь вам собрать больше информации об утечках памяти и других проблемах, связанных с памятью, является вкладка « Куча » на Android Device Monitor.
Вкладка « Куча » может помочь вам диагностировать утечки памяти, отображая объем памяти, выделенный системой вашему приложению. Как уже упоминалось, если выделенная память продолжает увеличиваться, это является сильным признаком того, что ваше приложение имеет утечку памяти.
Но этот инструмент также предоставляет много данных об использовании кучи вашего приложения, включая тип объектов, которые выделяет ваше приложение, количество выделенных объектов и сколько места занимают эти объекты. Эта дополнительная информация может быть неоценимой, когда вы отслеживаете источник утечек памяти и других проблем с памятью в вашем приложении.
Чтобы получить доступ к этому инструменту, запустите Android Device Monitor и выберите вкладку DDMS . На панели « Устройства» выберите свое устройство и процесс, который вы хотите проверить. Затем выберите вкладку « Куча », как показано на скриншоте ниже, и потратьте некоторое время на взаимодействие с вашим приложением.
Вывод кучи отображается только после события GC, поэтому, чтобы заполнить эту вкладку данными, вам нужно будет либо дождаться, пока событие GC произойдет естественным образом, либо вы можете принудительно вызвать GC, нажав кнопку Cause GC .
После того, как произошло событие GC, вкладка « Куча » обновится с большим количеством информации об использовании кучи в вашем приложении. Эти данные будут обновляться после каждого события GC.
Вывод
В этом руководстве мы рассмотрели некоторые из наиболее распространенных проблем с производительностью, которые необходимо учитывать при разработке приложений для Android, перерисовке, утечке памяти и медленном рендеринге пользовательского интерфейса.
Вы также познакомились с некоторыми инструментами, которые вы можете использовать, чтобы проверить, возникают ли эти проблемы в ваших собственных проектах Android, и узнали, как собрать больше информации о любых проблемах производительности, возникающих в ваших собственных приложениях. Чем больше у вас информации, тем больше у вас шансов отследить причину проблемы и устранить ее.
В Android SDK имеется гораздо больше инструментов, которые могут помочь вам диагностировать и решать проблемы с производительностью. Если вы хотите узнать больше, то официальные страницы документации Android по Traceview и dmtracedump и Allocation Tracker содержат больше информации.