- Эффективное использование GPU
- Настроить параметры GPU визуализации
- Отладить показатель GPU overdraw
- Как разогнать Android-смартфон через меню разработчиков
- Настройки разработчика Android
- Как ускорить Android
- Повысить быстродействие смартфона
- GPU-ускорение на Android — что это и нужно ли включать?
- Нужно ли включать GPU-ускорение на телефоне?
- Разработка быстрых мобильных приложений на Android. Часть вторая
- Общие советы по работе с памятью
- Профилирование GPU
- Hierarchy Viewer
- Overdraw
- Альфа
- Аппаратное ускорение
- Сделай сам
- Больше информации
- Другие интересные ссылки
Эффективное использование GPU
Разработчику следует научиться эффективно использовать графический процессор устройства (GPU), чтобы приложение не тормозило и не выполняло лишнюю работу.
Настроить параметры GPU визуализации
Если ваше приложение тормозит, значит часть или все кадры обновления экрана обновляются больше чем 16 миллисекунд. Чтобы визуально увидеть обновления кадров на экране, можно на устройстве включить специальную опцию Настроить параметры GPU визуализации (Profile GPU Rendering).
У вас появится возможность быстро увидеть, сколько времени занимает отрисовка кадров. Напомню, что нужно укладываться в 16 миллисекунд.
Опция доступна на устройствах, начиная с Android 4.1. На устройстве следует активировать режим разработчика. На устройствах с версией 4.2 и выше режим по умолчанию скрыт. Для активации идёт в Настройки | О телефоне и семь раз щёлкаем по строке Номер сборки.
После активации заходим в Опции разработчика и находим пункт Настроить параметры GPU визуализации (Profile GPU rendering), который следует включить. В всплывающим окне выберите опцию На экране в виде столбиков (On screen as bars). В этом случае график будет выводиться поверх запущенного приложения.
Вы можете протестировать не только своё приложение, но и другие. Запустите любое приложение и начинайте работать с ним. Во время работы в нижней части экрана вы увидите обновляемый график. Горизонтальная ось отвечает за прошедшее время. Вертикальная ось показывает время для каждого кадра в миллисекундах. При взаимодействии с приложением, вертикальные полосы рисуются на экране, появляясь слева направо, показывая производительность кадров в течение какого-то времени. Каждый такой столбец представляет собой один кадр для отрисовки экрана. Чем выше высота столбика, тем больше времени уходит на отрисовку. Тонкая зелёная линия является ориентиром и соответствует 16 миллисекундам за кадр. Таким образом, вам нужно стремиться к тому, чтобы при изучении вашего приложения график не выбивался за эту линию.
Рассмотрим увеличенную версию графика.
Зелёная линия отвечает за 16 миллисекунд. Чтобы уложиться в 60 кадров в секунду, каждый столбец графика должен рисоваться ниже этой линии. В каких-то моментах столбец окажется слишком большим и будет гораздо выше зелёной линии. Это означает торможение программы. Каждый столбец имеет голубой, фиолетовый (Lollipop и выше), красный и оранжевый цвета.
Голубой цвет отвечает за время, используемое на создание и обновление View.
Фиолетовая часть представляет собой время, затраченное на передачу ресурсов рендеринга потока.
Красный цвет представляет собой время для отрисовки.
Оранжевый цвет показывает, сколько времени понадобилось процессору для ожидания, когда GPU завершит свою работу. Он и является источником проблем при больших величинах.
Существуют специальные методики для уменьшения нагрузки на графический процессор.
Отладить показатель GPU overdraw
Другая настройка позволяет узнать, как часто перерисовывается один и тот же участок экрана (т.е. выполняется лишняя работа). Опять идём в Опции разработчика и находим пункт Отладить показатель GPU overdraw (Debug GPU Overdraw), который следует включить. В всплывающим окне выберите опцию Показывать зоны наложения (Show overdraw areas). Не пугайтесь! Нкоторые элементы на экране изменят свой цвет.
Вернитесь в любое приложение и понаблюдайте за его работой. Цвет подскажет проблемные участки вашего приложения.
Если цвет в приложении не изменился, значит всё отлично. Нет наложения одного цвета поверх другого.
Голубой цвет показывает, что один слой рисуется поверх нижнего слоя. Хорошо.
Зелёный цвет — перерисовывается дважды. Нужно задуматься об оптимизации.
Розовый цвет — перерисовывается трижды. Всё очень плохо.
Красный цвет — перерисовывается много раз. Что-то пошло не так.
Вы можете самостоятельно проверить своё приложение для поиска проблемных мест. Создайте активность и поместите на неё компонент TextView. Присвойте корневому элементу и текстовой метке какой-нибудь фон в атрибуте android:background. У вас получится следующее: сначала вы закрасили одним цветом самый нижний слой активности. Затем поверх неё рисуется новый слой от TextView. Кстати, на самом TextView рисуется ещё и текст.
В каких-то моментах наложения цветов не избежать. Но представьте себе, что вы таким же образом установили фон для списка ListView, который занимает все площадь активности. Система будет выполнять двойную работу, хотя нижний слой активности пользователь никогда не увидит. А если вдобавок вы создадите ещё и собственную разметку для каждого элемента списка со своим фоном, то вообще получите перебор.
Маленький совет. Поместите после метода setContentView() вызов метода, который уберёт перирисовку экрана цветом темы. Это поможет убрать одно лишнее наложение цвета:
Источник
Как разогнать Android-смартфон через меню разработчиков
Медлительность Android по сравнению с iOS всегда была мифом, в который почему-то верили миллионы человек. Просто дизайнеры Apple скрыли задержку от запуска приложения до его фактического открытия анимацией, а в Google до этого не додумались. Таким же мифом является склонность Android к засорению и замедлению через какое-то время после начала использования. Дескать, системные кластеры забиваются и уже не могут обеспечивать былой уровень быстродействия. Вот только никто не говорит, что обычно «замедляются» именно старые устройства и только в сравнении с новыми. Но это не значит, что разогнать Android нельзя совсем. Можно.
Разогнать Android можно. Для этого в настройках ОС есть специальные параметры
В Android есть так называемое меню разработчиков. Несмотря на то что оно действительно предназначается для создателей программного обеспечения, рядовые пользователи очень любят включать его, а потом что-то там настраивать и менять, якобы улучшая работу своего устройства. Зачастую это, само собой, совершенно не так. Однако есть несколько надстроек, которые могут позволить хоть немного, но ускорить Android, сделав его чуть отзывчивее, быстрее и податливее. Главное – не переборщить.
Настройки разработчика Android
Для начала нам потребуется активировать меню разработчиков. Если оно у вас уже есть, переходите сразу к третьему пункту инструкции, а если нет – начинайте с первого. Но помните, что активация этих параметров может привести к повышенному ресурсопотреблению и сокращению времени автономной работы.
- Перейдите в «Настройки» и откройте раздел «Об устройстве»;
- Найдите вкладку «Номер сборки» и 10 раз быстро на неё нажмите;
Все необходимые параметры скрыты в меню разработчиков
- Вернитесь назад, а затем перейдите в меню «Для разработчиков»;
- Пролистайте вниз и включите параметр «Ускорить работу GPU»;
- Пролистайте далее и включите пункт «Включить 4x MSAA»;
Активируйте три этих параметра и отключите анимацию
- Затем включите пункт «Отключить аппаратное наложение»;
- В разделе «Скорость анимации» выберите значение x0,5 или x0.
Как ускорить Android
Разогнать Android можно и в играх, и при работе с интерфейсом
Эти три параметра действительно способны разогнать интерфейс вашего смартфона. Вот как это происходит:
Ускорение работы GPU активирует графический ускоритель при отрисовке двумерных элементов. Казалось бы, зачем вообще это нужно? А, между тем, весь интерфейс вашего смартфона и большинство сайтов целиком состоят из 2D-элементов. Активировав ускорение, вы заставите смартфон задействовать графический сопроцессор при обработке всех этих компонентов, а поскольку их в повседневной жизни встречается довольно много, то и прирост быстродействия будет заметен в большинстве задач.
Включение параметра 4x MSAA способно напрямую повлиять на ваше восприятие игр. Независимо от того, двумерная или трёхмерная игра запущена на вашем устройстве, этот пункт повышает контурную детализацию, минимизируя рябь и подёргивания на краях рисованных объектов. В результате создаётся ощущение более плавной обработки видимых графических компонентов. Если хотите, это совсем дешёвый аналог режима 120 Гц, повышающего частоту обновления и делающего картинку более плавной.
Повысить быстродействие смартфона
Ускорить даже интерфейс Android — это уже большое дело
Отключение аппаратного наложения позволяет задействовать графический сопроцессор при отрисовке компонентов экрана, за счёт чего высвобождается ресурс центрального процессора, и он больше не нагружается в базовых задачах. Может показаться, что этот параметр полностью противоречит первому, но это не совсем так. Вернее, совсем не так. Просто они отвечают за разные процессы.
Смените раскрытые пароли. Что это значит и как реагировать
Изменение скорости анимации – это чисто визуальный, или, если хотите, косметический показатель. В действительности он не повышает скорость запуска приложений, просто он удаляет анимацию, которая по умолчанию заполняет «пустоту» от момента запуска приложения до момента его активации. Но если раньше такая пустота действительно была, и её требовалось чем-то заполнять, то современные смартфоны её практически не допускают. В результате кажется, что приложения из-за анимации запускаются чуть дольше.
Новости, статьи и анонсы публикаций
Свободное общение и обсуждение материалов
Android, в отличие от iOS, — система более открытая и свободная. Здесь нет тех ограничений, которые Apple устанавливает для владельцев iPhone. Поэтому среди пользователей Android считается нормой скачивать приложения не только из Google Play, но и из-за его пределов. Иногда это обусловлено нежеланием платить за софт деньги, а иногда – банальным отсутствием нужного приложения в официальном каталоге. Однако в Google считают, что при всех допущениях Android существует только один правильный способ загрузки софта.
Телеграм уже давно завоевал звание лучшего мессенджера в сети. Спорить с этим просто глупо. Его простота и функциональность сведут с ума любого пользователя. Кроме того, видно, как команда чувствует перспективу и регулярно вносит правки в свой продукт. Но, как и любой другой проект, Телеграм нуждается в монетизации. Павел Дуров уже не один раз говорил, что содержит свое детище в убыток. И совсем недавно решился на радикальный шаг — добавление рекламы. Понятно, что все сразу сбежались на неприятное слово и повалили хейта, толком не разобравшись в сути. Но люди с головой посмотрели в корень и увидели, что его подход к вопросу — один из лучших на рынке. Теперь Павел и вовсе объявил о подписке, с помощью которой можно от нее избавиться. Браво!
Несмотря на то что многие по-прежнему скептически относятся к системе «умный дом», надо признать, что существуют безоговорочно удачные изобретения. Если голосовое управление освещением или кондиционером – штука весьма сомнительная, то вот оспаривать удобство роботов-пылесосов, пожалуй, не решится никто. Потому что реально удобно, когда маленькая штуковина как по разнарядке каждое утро выезжает на уборку, оставляя после себя тотальную чистоту. Правда, чтобы всё было именно так, нужно выбрать правильный робот-пылесос.
Источник
GPU-ускорение на Android — что это и нужно ли включать?
Смартфоны на Android с каждым годом работают быстрее: производители устанавливают новые процессоры и GPU, увеличивают объем оперативной памяти. Сегодня мобильное устройство может заменить ноутбук — мощности гаджета хватит, чтобы полноценно пользоваться интернетом и даже обрабатывать видео.
В операционной системе Android есть дополнительные функции, которые помогут увеличить скорость работы смартфона. Один из таких инструментов — GPU-ускорение.
Нужно ли включать GPU-ускорение на телефоне?
GPU — встроенный графический процессор. Задача GPU-ускорения — принудительный перенос процесса рендеринга изображения с процессора смартфона на GPU. Таким образом повышается общая производительность мобильного устройства — после активации этого режима увеличивается скорость обработки информации в производительных играх и приложениях (утилиты для обработки и рендеринга видеороликов, фотографий, графические приложения).
Если в некоторых играх или программах снижается производительность, активируйте GPU-ускорение. Это не навредит смартфону, единственное, что может произойти — некоторые утилиты перестанут запускаться.
Для включения GPU-ускорения откройте настройки гаджета. После этого перейдите в раздел «Для разработчиков» — вот подробная инструкция по его открытию.
В меню разработчиков находится подраздел «Аппаратное ускорение визуализации». Активируйте функцию «GPU-ускорение». Теперь гаджет будет использовать максимальное количество системных ресурсов, чтобы обеспечить высокую производительность в приложениях.
Источник
Разработка быстрых мобильных приложений на Android. Часть вторая
В Edison мы часто сталкиваемся с оптимизацией мобильных приложений и хотим поделиться материалом, который считаем крайне полезным, если вы решаете одну из двух задач: а) хотите чтобы приложение меньше тормозило; б) хотите сделать красивый, мягкий и гладкий интерфейс для массового пользователя.
Предлагаем вашему вниманию первую часть перевода статьи Udi Cohen, которую мы использовали как пособие для обучения молодых коллег оптимизации под Android.
Общие советы по работе с памятью
Вот несколько простых рекомендаций, которые я использую при написании кода.
- Перечисления уже являются предметом горячих споров о производительности. Вот видео, в котором обсуждается размер памяти, который тратят перечисления, и обсуждение данного видео и некоторой информации, потенциально вводящей в заблуждение. Используют ли перечисления больше памяти, чем обычные константы? Определенно. Плохо ли это? Не обязательно. Если вы пишете библиотеку и нуждаетесь в сильной типобезопасности, она могла бы оправдать их использование по сравнению с другими решениями, такими как @IntDef. Если у вас просто есть куча констант, которые могут быть сгруппированы вместе, использование перечислений будет не очень мудрым решением. Как обычно, есть компромисс, который нужно учесть при принятии решения.
Обёртка — это автоматическое конвертирование примитивных типов к их объектному представлению (например, int -> Integer). Каждый примитивный тип «оборачивается» в объектное представление, создается новый объект (шокирует, я знаю). Если у нас есть много таких объектов, вызов сборщика мусора будет выполняться чаще. Легко не заметить количество оборачиваний, потому что это делается автоматически для нас при назначении примитивному типу объекта. В качестве решения, постарайтесь использовать соответствующие типы. Если вы используете примитивные типы в своем приложении, постарайтесь избежать их обёртки без реальной на то необходимости. Вы можете использовать инструменты профилирования памяти, чтобы найти объекты, представляющие примитивные типы. Вы также можете использовать Traceview и искать Integer.valueOf(), Long.valueOf() и пр.
HashMap vs ArrayMap / Sparse*Array — также, как и в случае с обёртками, использование HashMap требует использование объектов в качестве ключей. Если мы используем примитивный тип int в своем приложении, он автоматически оборачивается в Integer при взаимодействии с HashMap, в этом случае мы могли бы использовать SparseIntArray. В случае, когда мы по-прежнему используем объекты в качестве ключей, мы можем использовать ArrayMap. Оба варианта требуют меньший объем памяти, чем HashMap, но они работают по-другому, что делает их более эффективными в потреблении памяти ценой уменьшения скорости. Обе альтернативы имеют меньший отпечаток памяти, чем HashMap, но время, требуемое для извлечения элемента или выделения памяти, немного выше, чем у HashMap. Если у вас нет более 1000 элементов, различия во времени выполнения не существенны, что делает жизнеспособными эти два вариантом.
Осознание контекста — как вы видели ранее, относительно легко создать утечки памяти. Вы, возможно, не будете удивлены, узнав, что активити являются наиболее частой причиной утечек памяти в Android(!). Их утечки также очень дорого стоят, так как они содержат все представления иерархии их UI, которые сами по себе могут занять много места. Убедитесь в том, что понимаете, что происходит в активити. Если ссылка на объект в кэше и этот объект живет дольше, чем ваша активити, без очистки этой ссылки вы получите утечку памяти.
Избегайте использование нестатических внутренних классов. При создании нестатического внутреннего класса и его экземпляра вы создаете неявную ссылку на ваш внешний класс. Если экземпляр внутреннего класса необходим на более длительный период времени, чем внешний класс, внешний класс будет продолжать находиться в памяти, даже если он больше не нужен. Например, создается нестатический класса, который наследует AsyncTask внутри класса Activity, затем происходит переход к новой асинхронной задаче и, пока она длится, завершение работы активити. Пока длится эта асинхронная задача, она будет сохранять активити живой. Решение простое — не делайте этого, объявите внутренний статический класс, если это необходимо.
Профилирование GPU
Новым добавлением в Android Studio 1.4 является профилирование GPU рендеринга.
Под окном Android перейдите на вкладку GPU, и вы увидите график, показывающий время, которое потребовалось, чтобы сделать каждый кадр на экране:
Каждая панель на графике представляет собой один отрисованный кадр, а цвет представляет различные этапы процесса.
- Draw (синий) — представляет метод View#onDraw(). Эта часть строит/обновляет объекты DisplayList, которые затем будут конвертированы в OpenGL команды, понятные для GPU. Высокие показатели могут быть из-за сложных используемых представлений, требующих больше времени для построения их списка отображения, либо много представлений стали недействительными в короткий промежуток времени.
Prepare (фиолетовый) — в Lollipop был добавлен ещё один поток, чтобы помочь отрисовывать UI быстрее. Он называется RenderThread. Он отвечает за преобразование списков отображения в OpenGL команды и отправку их графическому процессору. Как только это происходит, поток UI может переходить к обработке следующего кадра. Время, затраченное потоком UI, чтобы передать все необходимые ресурсы RenderThread, отражается на данном этапе. Если у нас длинные/тяжелые списки отображения, этот шаг может занять больше времени.
Process (красный) — выполнение списков отображения для создания OpenGL команд. Этот шаг может занять больше времени, если списки длинные или сложные, потому что необходимо перерисовать множество элементов. Представление может быть перерисовано, так как стало недействительным или было открыто после передвижения скрывающего его представления.
В Marshmallow было добавлено больше цветов для отображения большего количества шагов, таких как Measure/Layout, Input Handing и другие:
EDIT 09/29/2015: John Reck, фреймворк инженер из Google, добавил следующую информацию про некоторые из этих цветов:
«Точное определение слова «анимация» — это всё, что зарегистрировано с Choreographer как CALLBACK_ANIMATION. Это включает в себя Choreographer#postFrameCallback и View#postOnAnimation, которые используются view.animate(), ObjectAnimator, Transitions и другие… И да, это то же самое, что и отмечается меткой «анимация» в systrace.
«Misc» это задержка между временной меткой vsync и текущей временной меткой, когда он был получен. Если вы уже видели логи из Choreographer «Missed vsync by blabla ms skipping blabla frames», сейчас это будет представлено как “misc”. Существует различие между INTENDED_VSYNC и VSYNC в framestats dump (https://developer.android.com/preview/testing/performance.html#timing-info).»
Но перед тем как начать использовать эту возможность, нам необходимо включить режим GPU рендеринга в меню разработчика:
This will allow the tool to use ADB commands to get all the information it needs, and so are we (!), using:
можем получить информацию и построить график самостоятельно. Команда выведет полезную информацию, такую как число элементов в иерархии, размер всех списков отображения и прочее. В Marshmallow мы получим больше информации.
Если у нас есть автоматизированное тестирование UI нашего приложения, мы можем сделать сборку, запускающую эту команду после определенных действий (прокрутка списка, тяжелая анимация и др.) и увидеть, есть ли изменения в значениях, таких как «Janky Frames», с течением времени. Это может помочь определить упадок производительности после нескольких изменений в коде, позволяя нам устранить проблему, пока приложение не вышло на рынок. Мы можем получить еще более точную информацию, когда используем ключевое слово «framestats», как это показано здесь.
Но это не единственный способ увидеть такой график!
Как видно в меню разработчика «Profile GPU Rendering», есть также вариант “On screen as bars”. Его выбор покажет график для каждого окна на вашем экране вместе с зеленой линией, указывающей на порог 16 мс.
На примере справа мы можем видеть, что некоторые фреймы пересекают зеленую линию, что означает, что они требуют более 16мс для отрисовки. Поскольку синий цвет, кажется, доминирует, мы понимаем, что было много представлений для отрисовки, или они были сложными. В этом случае, я прокручиваю ленту, которая поддерживает различные типы представления. Некоторые элементы становятся недействительными, а некоторые — более сложными по сравнению с другими. Возможно, причина, по которой некоторые кадры пересекли эту черту, в том, что попался сложный для отображения элемент.
Hierarchy Viewer
Я обожаю этот инструмент, и мне очень жаль, что многие его не используют!
Используя Hierarchy Viewer, мы можем получить статистику производительности, увидеть полную иерархию представления на экране и иметь доступ ко всем свойствам элемента. Вы также можете сделать дамп всех данных темы, увидеть все параметры, используемые для каждого атрибута стиля, но это возможно только если Hierarchy Viewer запущен standalone, не из Android Monitor. Я использую этот инструмент, когда создаю макеты приложения и хочу оптимизировать их.
По центру мы можем видеть дерево, отражающее иерархию представления. Иерархия представления может быть широкой, но если она слишком глубокая (
10 уровней), это может нам дорого стоить. Каждый раз, когда происходит измерения представления в View#onMeasure(), или когда размещаются его потомки в View#onLayout(), эти команды распространяются на потомков этих представлений, делая то же самое. Некоторые макеты будут делать каждый шаг дважды, например, RelativeLayout и некоторые LinearLayout конфигурации, и если они вложены — число проходов увеличивается в геометрической прогрессии.
В нижнем правом углу мы можем видеть «план» нашего макета, отмечая, где каждое представление располагается. Мы можем выбрать представление здесь, или на дереве и увидеть слева все свойства. При проектировании макета я иногда не уверен, почему определенное представление заканчивается там, где оно заканчивается. Используя этот инструмент, я могу отследить на дереве, выбрать его и увидеть, где он находится в окне предварительного просмотра. Я могу сделать интересные анимации, глядя на итоговые измерения представлений на экране, и использовать эту информацию, чтобы точно размещать элементы вокруг. Я могу найти потерянные представления, которые были перекрыты другими представлениями непреднамеренно.
Для каждого представления у нас есть время, которое потребовалось для измерения/создания макета/отрисовки его и всех его потомков. Цвета отражают, как эти представления выполняются в сравнении с другими представлениями в дереве, это отличный способ найти слабое звено. Поскольку мы также видим предпросмотр представления, мы можем пройти по дереву и следовать инструкциям, создающим их, находя лишние шаги, которые мы могли бы удалить. Одна из таких вещей, которая влияет на производительность, называется Overdraw.
Overdraw
Как видно в разделе профилирования GPU — фаза Execute, представленная желтым цветом на графике, может занять больше времени, чтобы завершиться, если GPU должен отрисовать много элементов, увеличивая время, требуемое для отрисовки каждого кадра. Overdraw происходит когда мы рисуем что-то поверх чего-то другого, например желтую кнопку на красном фоне. GPU требуется нарисовать, во-первых, красный фон и затем желтую кнопку поверх него, что делает неизбежным overdraw. Если у нас слишком много слоев overdraw, это может стать причиной, по которой GPU работает интенсивнее и не успевает в 16 мс.
Используя настройку «Debug GPU Overdraw» в меню разработчика, все overdraw будут подкрашены, чтобы продемонстрировать степень overdraw в данной области. Если overdraw имеет степень 1x/2x, это нормально, даже небольшие красные области это тоже неплохо, но если мы имеем слишком много красных элементов на экране, вероятно у нас есть проблема. Давайте посмотрим на несколько примеров:
На примере слева присутствует список, окрашенный зеленым, обычно это нормально, но здесь есть overdraw наверху, который делает экран красным, и это уже становится проблемой. На примере справа весь список светло-красный. В обоих примерах есть непрозрачный список с 2x/3x степенью overdraw. Эти может случиться, если есть фоновый цвет на весь экран в окне, которое перекрывает ваш активити или фрагмент, а также на представлении списка и представлении каждого его элемента.
Заметьте: тема по умолчанию задает фоновый цвет для всего вашего окна. Если у вас есть активити с непрозрачным макетом, который перекрывает весь экран, вы можете убрать задний фон для этого окна, чтобы убрать один слой overdraw. Это может быть сделано в теме или в коде путем вызова getWindow().setBackgroundDrawable(null) в onCreate().
Используя Hierarchy Viewer, вы можете экспортировать все ваши слои иерархии в PSD файл, чтобы открыть его в Photoshop. В результате исследования различных слоев будут раскрыты все overdraw в макете. Используйте эту информацию, чтобы убрать избыточные overdraws, и не соглашайтесь на зеленый, стремитесь к голубому!
Альфа
Использование прозрачности может повлиять на производительность, и для того, чтобы понять — почему, давайте посмотрим, что происходит при установке параметра альфа в представлении. Рассмотрим следующую структуру:
Мы видим макет, который содержит 3 ImageView, которые перекрывают друг друга. В прямой реализации, устанавливая альфа с помощью setAlpha(), будет вызвана команда, чтобы распространиться на всех представления потомков, ImageView в данном случае. Затем эти ImageView будут нарисованы с параметром alpha в буфере кадра. Результат:
Это не то, что мы хотим видеть.
Поскольку каждый ImageView был отрисован со значением альфа, все перекрывающиеся изображения сольются. К счастью, у ОС есть решение такой проблемы. Макет будет скопирован в отдельный off-screen буфер, альфа будет применяться в этом буфере в целом и результат будет скопирован в буфер кадра. Результат:
Но… мы заплатим за это свою цену.
Дополнительная отрисовка представления в off-screen буфере до того, как это будет сделано в буфере кадра, добавляет еще один незаметный overdraw слой. ОС не знает, когда именно использовать этот или прямой подход раньше, так что по умолчанию всегда использует один комплексный. Но есть еще способы, позволяющие установить альфа и избежать сложностей с добавлением off-screen буфера:
- TextViews — используйте setTextColor() вместо setAlpha(). Использование канала альфа для текста приведет к тому, текст будет перерисован.
- ImageView — используйте setImageAlpha() вместо setAlpha(). Те же причины, что и для TextView.
- Пользовательские представления — если наше пользовательское представление не поддерживает перекрытия, это комплексное решение не имеет для нас значение. Нет способа, которым наши представления-потомки будут соединены вместе, как это показано на примере выше. Переопределив метод hasOverlappingRendering() таким образом, чтобы он возвращал false, мы сигнализирует ОС взять непосредственно путь к нашему представлению. Также есть вариант вручную обрабатывать то, что происходит при установке альфа путем переопределения метода onSetAlpha() так, чтобы он возвращал true.
Аппаратное ускорение
Когда аппаратное ускорение было включено в Honeycomb, мы получили новую модель отрисовки для отображения нашего приложения на экране. Это включает структуру DisplayList, которая записывает команды отрисовки представления для более быстрого получения изображения. Но есть еще другая интересная особенность, о которой разработчики обычно забывают — уровни представления.
Используя их, мы можем отрисовывать представление в off-screen буфере (как мы видели ранее, когда использовали альфа-канал) и манипулировать с ним как мы пожелаем. Это отлично подходит для анимации, поскольку мы можем анимировать сложные представления быстрее. Без уровней анимация представлений стала бы недоступной после изменения свойств анимации (таких как x-координата, масштаб, альфа-значение и др.). Для сложных представлений эта неспособность распространяется на представления потомков, и они в свою очередь будут перерисовывать себя, что является дорогостоящей операцией. Используя уровни представления, опираясь на аппаратные средства, текстура для нашего представления создается в графическом процессоре. Существует несколько операций, которые мы можем применить к текстуре, без необходимости её замены, такие как изменение положения по осям x/y, вращение, альфа и другие. Всё это означает, что мы можем анимировать сложные представления на нашем экране без их замены в процессе анимации! Это делает анимацию более гладкой. Вот пример кода, демонстрирующий, как это можно сделать:
Да, но есть несколько моментов, о которых нужно помнить при использовании аппаратного уровня.
- Делайте очистку после работы вашего представления — аппаратный уровень использует место на ограниченном пространстве памяти на вашем GPU. Попробуйте использовать его только в случаях, когда он нужны, например, в анимации, и делайте очистку после. В примере выше с ObjectAnimator я использовал метод withLayers(), который автоматически создает слой в начале и удаляет его, когда анимация заканчивается.
- Если вы изменяете ваше представление после использования аппаратного уровня, это приведет к его непригодности и придется вновь воспроизводить представление на off-screen буфере. Это произойдет, когда изменится свойство, не оптимизированное для аппаратного уровня (на данный момент оптимизированы: поворот, масштабирование, передвижения по осям x/y, альфа). Например, если вы анимируете представление, используя аппаратный уровень, и двигаете представление по экрану, пока обновляется цвет фона, это приведет к постоянным обновлениям на аппаратном уровне. Это требует дополнительных расходов, которые могут сделать его использование неоправданным.
Для второго случая есть способ визуализировать это обновление. Используя настройки разработчика, мы можем активировать “Show hardware layers updates”.
После этого представление будет подсвечивается зеленым цветом при обновления на аппаратном уровне. Я использовал это некоторое время назад, когда у меня был ViewPager, который не пролистывал страницы с тем сглаживанием, которое я ожидал. После того, как я включил эту опцию, я вернулся назад и пролистал ViewPager, и вот что я увидел:
Обе страницы были зелеными на протяжении всей прокрутки!
Это означает, что для оптимизации страниц использовался аппаратный уровень, и страницы приходили в негодность, когда мы пролистывали ViewPager. Я обновил страницы и пролистал их, используя параллакс-эффект на заднем фоне и постепенно оживил элементы на странице. Что я не сделал, так это не создал аппаратный слой для страниц ViewPager. После изучения кода ViewPager я обнаружил, что когда пользователь начинает пролистывание, на аппаратном уровне создаются обе страницы и удаляются после того, как пролистывание заканчивается.
В то время как имеет смысл использовать аппаратные уровни для пролистывания страниц, в моем случае это не подошло. Обычно страницы не изменяются, когда мы пролистываем ViewPager, и поскольку они могут быть достаточно сложными, аппаратный уровень помогают делать отрисовку гораздо быстрее. В приложении, над которым я работал, это было не так, и я убрал этот аппаратный слой, используя небольшой хак, который я написал сам.
Аппаратный слой — не серебряная пуля. Важно понимать, как он работает, и использовать должным образом, иначе вы можете столкнуться с большой проблемой.
Сделай сам
При подготовке для всех этих примеров, показанных здесь, я написал множество кода для симуляции этих ситуаций. Вы можете найти их на репозитории Github, а также на Google Play. Я разделил сценарии для различных активити, и старался задокументировать их насколько возможно, чтобы помочь понять, с какого рода проблемами вы можете столкнуться, используя активити. Прочтите документацию по активити, откройте инструменты и поиграйте с приложением.
Больше информации
По мере развития ОС Android развиваются и способы, с помощью которых вы можете оптимизировать ваши приложения. Новые инструменты вводятся в Android SDK, добавляются и новые функции в ОС (например, аппаратные уровни). Очень важно осваивать новое и изучать компромиссы, прежде чем решить что-то изменить.
Есть замечательный плейлист на YouTube, который называется Android Performance Patterns, с множеством коротких видео от Google, объясняющими различные вещи, связанные с производительностью. Вы можете найти сравнения между различными структурами данных (HashMap vs ArrayMap), оптимизацию Bitmap и даже про оптимизацию сетевых запросов. Я очень рекомендуют посмотреть всех их.
Вступите в Android Performance Patterns Google+ community и обсуждайте производительность с другими участниками, включая сотрудников Google, чтобы поделиться идеями, статьями и вопросами.
Другие интересные ссылки
- Изучите, как работает Graphics Architecture in Android. Там есть все, что вам надо знать про отрисовку вашего UI в Android, объясняются различные системные компоненты, такие как SurfaceFlinger, и как они все друг с другом взаимодействуют.
Talk from Google IO 2012 показывает как работает модель отрисовки и как/почему мы получаем мусор, когда наше UI отрисовывается.
Android Performance Workshop talk из Devoxx 2013 демонстрирует некоторые оптимизации, которые были сделаны в Android 4.4 в модели отрисовки, и представляет различные инструменты для оптимизации производительности (Systrace, Overdraw и др.).
Замечательный пост о Профилактической оптимизации, и чем она отличаются от Преждевременной оптимизации. Многие разработчики не оптимизируют свой код, потому что они думают, что это изменение незначительно. Одна мысль, которую вы должны запомнить, это то, что все это в сумме становится большой проблемой. Если у вас есть возможность оптимизировать только небольшую часть кода, это может показаться незначительным, не исключаю.
Управление памятью в Android — старое видео с Google IO 2011, которое всё еще актуально. Оно демонстрирует, как Android управляет памятью наших приложений, и как использовать инструменты, такие как Eclipse MAT, чтобы выявить проблемы.
Я надеюсь, у вас теперь есть достаточно информации, и больше уверенности, чтобы начать оптимизацию приложений уже сегодня!
Начните трассировку, или включите некоторые другие доступные опции разработчика, и просто начните с них. Предлагаю поделиться вашими мыслями в комментариях.
Источник