Чуть-чуть про перформанс UI в Android

👁 450

Спойлерок

Привет! Это пишет b00blik уже из будущего. Прошло несколько лет, и потому этот пост может быть слегка неактуален. Зато у меня есть другие рассказы: как я наполучал лещей в поиске иностранного оффера, как нищал русский айтишник в 2022, да даже про пинбол что-то есть. Залетай, расскажу!

Привет! Вы когда-нибудь задумывались, почему android-приложение может страшно тормозить? На самом деле, для этого может быть ряд причин, о которых я расскажу немного позже. А пока — список полезных тул, которые могут пригодиться, если вы собираетесь отлавливать странности при работе вашего приложения:

  • Это, конечно, мониторы. Они находятся во вкладке «Android monitor». Это довольно примитивно, но общую картину производительности они безусловно дают. androidmonitors
  • Android Device Monitor

Есть такое средство, которое по сути позволяет работать с несколькими полезными тулами:

  1. DDMS
  2. Tracer for OpenGL ES
  3. Hierarchy Viewer
  4. Systrace

Вскользь пробежимся по ним.

DDMS. Крайне удобная штука, позволяет смотреть потоки которые выполняются, чекать хип памяти, смотреть работу с сетью, трекать выделение памяти для объектов и работать с файловой системой мобильника.

debug-ddms

Tracer for OpenGL ES. Это хорошая вещь, которая тоже меня выручала. Как уже ясно из названия, эта штука позволяет смотреть трейс вызовов OpenGL для каждого фрейма. Можно посмотреть, что именно долго выполняется.

Hierarchy Viewer в свою очередь показывает насколько сложная структура у вашего layout’а, отсюда можно посмотреть что у нас долго рисуется, где проблемы, которые нужно решить.

hv_view_hierarchy_window
hv_treeview_screenshot

Теперь расскажу о своем опыте, когда пришлось импрувнуть производительность UI в приложении.

Было такое дело, что в одном приложении был список, который мог расти вплоть до 1000 элементов. Было замечено, что там используется ListView. Напомню, чем отличается ListView от RecyclerView.

Общей рекомендацией при работе с ListView является использование паттерна ViewHolder. Суть его заключается в том, что для каждого элемента списка создаётся объект, хранящий ссылки на отдельные View внутри элемента. Таким образом, приходится выполнять достаточно дорогой вызов findViewById() только один раз при создании элемента. А ссылка на такой ViewHolder для каждого элемента сохраняется в корневом layout, используя метод setTag(). Но! Но. Использование этого паттерна необязательно (можно было бы заюзать адаптер создающий с нуля отдельную вьюшку для каждого итема).

RecyclerView можно считать усовершенствованным ListView. Тут правда от ViewHolder никуда не деться, плюс ко всему там добавлен LayoutManager который, внимание, решает переиспользовать или нет View-шку для итема. Считай, именно киллер-фича этого RecyclerView заключается в переиспользовании View-шек и меньшем расходе памяти.

То есть понятно, что нужно было первым делом сменить ListView на RecyclerView? 🙂

И кстати говоря, если после этого приложение всё равно тормозит — рекомендую обратить внимание на systrace. Посмотрите вызовы методов которые происходят у вас в Adapter, они ведь работают в UI по умолчанию. Быть может, их стоит вынести в Background поток?

И еще одна важная тема, которая влияет на перформанс в UI, это overdrawing. Да, причиной тормозов может оказаться то, что картинка у вас слишком часто перерисовывается!

Давайте посмотрим, как это можно задетектить.

Включим отладку наложения в меню разработчика:

overdraw

нужно выбрать «выделять области определенного цвета»

И запустим какое-нибудь приложение. ВК например:

redexample

Вот посмотрите, сколько разных цветов. Зеленый говорит о том, что пиксели рисуются один раз, розовый, что дела обстоят похуже, а красный — всё совсем плохо. Дикое число перерисовок. Если ваше приложение будет почти всё светиться красненьким — скорее всего будет страшно глючить.

Кстати, заметил такой момент, и предлагаю обратить на это внимание: backgroud. Да, тот самый, что у View-шки. Если у вас, допустим, он у ViewHolder’а жёлтый, и жёлтый у RecyclerView, и плюс ко всему у того что под Recycler’ом желтый, то… ну вы понимаете количество перерисовок? Нещадно выпиливайте его.

И пожалуй одна из важных вещей — отрисовка текста. Она всегда занимает много времени, поэтому мне кажется стоит посоветовать делать так, чтобы текста на экране было немного.

Конечно, это довольно краткий рассказ о том, что можно использовать при исследовании производительности Android-приложения, но, надеюсь, что-то здесь было полезно.

Из того что рекомендую:

  • Документация от гугла тыц
  • Performance Patterns на канале Android Developers в Ютабе тыц