О производительности Android-приложений
Введение Первое, что я хочу сказать: статья не претендует на сильно глубокий уровень, скорее я хочу рассказать о том, что производительность это не только «быстрее с NDK на С++» и «экономьте память, а то сборка мусора будет часто запускаться», а это целый комплекс мер, потому что проблемы с производительностью возникают не когда одна функция медленно работает, а в комплексе.Не было ли у вас ощущения, что приложение тормозит, а вы уже не знаете что делать — и память вроде не жрет, и профайлером уже посмотрели, а решения все нет. Если да, то эти заметки для вас.Понятия и термины я переводить не буду, так как я думаю что почти все разработчики их не переводят.Ссылки (да, ссылки вначале) Все что я описываю здесь я почерпнул из:1. Курс по производительность от Google (рекомендую);2. developer.android.com (если вы сюда не заглядывали, то у меня для вас плохие новости).Overdraw Как выглядит процесс превращения вашей xml-разметки в то, что вы видите на экране? Это довольно сложный процесс, но сейчас нас интересует одна деталь. На одном из этапов происходит растроризация (rasterization). Это тот самый процесс, когда высокоуровневые объекты вроде шрифтов и кружков делятся на пиксели.Представьте себе простой пример:
У нас есть TextView, которая лежит в LinearLayout, который тоже лежит в LinearLayout. И у каждого из них есть свой background. Это значит, что когда будет рисоваться TextView, оно будет рисоваться по уже нарисованному LinearLayout, часть которого тоже была нарисовано по уже нарисованному. Это и называется overdraw. Возможно, само по себе это не так критично, но говорит о том, что у есть проблемы, например, с иерархией.Для того, чтобы найти overdraw, нужно поставить галочку в настройках Android: Settings → Developer Options →Debug GPU Overdraw
И ваш телефон сразу преобразится!
Все сразу окрашивается в разные красивые цвета:
Синий цвет — все в порядкеЗеленый — 2x overdrawСветлокрасный — 3x overdrawКрасный — 4x и более
Вот так, например, выгдядит Gmail:
А вот так знакомое многим приложение Vivino:
Видно, у кого есть проблемы, а у кого нет.Первое, что можно сделать чтобы избавить от overdraw, это убрать лишние определения background. Например:
И, еще можно написать в Activity: @Override public void onCreate (Bundle savedInstanceState) { getWindow ().setBackgroundDrawable (null); … } Иерархия Построение дерева вьюх — весьма дорогой процесс. И общая рекомендация здесь очень проста — чем проще, тем лучше. Плоская разметка — идеально.Чтобы найти проблемные места в вашем приложении, можно использовать утилиту monitor, которая входит в набор Android SDK. В нем есть вид «Hierarchy View», и это то, что нам нужно.* о том как настроить и подробности читайте здесь: http://developer.android.com/training/improving-layouts/optimizing-layout.htmlи здесь: http://developer.android.com/tools/debugging/debugging-ui.html
Эта утилита показывает всю иерархию вьюх в приложении, и показывает насколько каждая вью производительнее (относительно остальных). Выглядит это примерно так:
Что показывают цветные точки monitor меряет скорость отрисовки вьюх для каждой фазы отрисовки Activity: Левая — DrawСредняя — LayoutПравая — MesureЧто касается цвета, то: Зеленый означает, что вью рендерится быстрее по крайней мере половины соседних вьюх.Yellow означает, что вью рендерится медленнее по крайней мере половины соседних вьюх.Красный говорит о том, что все плохо вью одна из самых времязатратных.Как трактовать эти точки? Если у вас все красное у «крайних» вью (те, что листы дерева), то на них точно стоит смотреть.Если у вас ViewGroup с большим количество детей, и у них точка показывающая measure красная, то тут точно надо смотреть на иерархию.В нашем примере, ее можно было бы сделать плоской достаточно легко:
Это можно и нужно использовать, если у вас часть разметки становится видимой только в каких-то случаях или по нажатию на какую-то кнопку. То есть, это что-то вроде ленивой инициализации.
Пишите быстрые приложения, коллеги.