Полезные функции в «режиме разработчика» на android

Потоки в Android

Запущенное в Android приложение имеет собственный процесс и как минимум один поток — так называемый главный поток (main thread). Если в приложении есть какие-либо визуальные элементы, то в этом потоке запускается объект класса Activity, отвечающий за отрисовку на дисплее интерфейса (user interface, UI).

В главном Activity должно быть как можно меньше вычислений, единственная его задача — отображать UI. Если главный поток будет занят подсчетом числа пи, то он потеряет связь с пользователем — пока число не досчиталось, Activity не сможет обрабатывать запросы пользователя и со стороны будет казаться, что приложение зависло. Если ожидание продлится чуть больше пары секунд, ОС Android это заметит и пользователь увидит сообщение ANR ( — «приложение не отвечает») с предложением принудительно завершить приложение.

Рис. 2. ANR-сообщение

Получить такое сообщение несложно — достаточно в главном потоке начать работу с файловой системой, сетью, криптографией и так далее. Как ты понимаешь, это очень плохая ситуация, которая не должна повторяться в штатных режимах работы приложения.

Looper

Было бы классно уметь перекидывать данные из одного потока в другой. В Android, как и любой Linux-системе, это возможно. Один из доступных в Android способов — это создать очередь сообщений (MessageQueue) внутри потока. В такую очередь можно добавлять задания из других потоков, заданиями могут быть переменные, объекты или кусок кода для исполнения (Runnable).

Чтобы организовать очередь, нужно воспользоваться классами Handler и Looper: первый отвечает за организацию очереди, а второй в бесконечном цикле проверяет, нет ли в ней новых задач для потока.

Запуск такого потока устроен по похожей схеме — создание нового объекта и вызов метода .

После выполнения этого метода создастся новый поток, который заживет своей жизнью. А это значит, что инициализация переменных и создание объектов будут уже идти параллельно с теми вызовами, которые забиты в следующих строчках после команды . Поэтому перед обращением к очереди в новом потоке нужно немного подождать — объект handler может еще не существовать.

Уберись на рабочем столе Андроид

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

Установка лаунчера, очень часто помогает сделать устройство более чистым. Я лично стараюсь ограничить рабочий стол своего смартфона одним рабочим столом. Это не ускорит Андроид, но ускорят мою работу со смартфоном, так как я могу быстрей перейти к нужному приложению.

Использование ViewModel для хранения данных пользовательского интерфейса

ViewModel предназначен для хранения данных, связанных с пользовательским интерфейсом, и управления ими с учетом жизненного цикла.

Во-первых, замените логику сохранения и восстановления состояния в MainFragment.kt подходом, использующим ViewModel.

В пакете viewmodels создайте новый класс с именем MainViewModel.kt.

Это будет ViewModel для вашего главного экрана. Вы будете использовать его для сохранения состояния DogCount. Используйте _dogCount для отслеживания состояния и dogCount для отображения его наблюдателям. Для обновления состояния используйте setDogCount().

Если вы хотите узнать больше о LiveData, обратитесь к Android Developer documentation.

В MainFragment.kt добавьте следующее:

Добавьте следующую строку выше onCreate():

Таким образом, вы добавили код для создания MainViewModel для MainFragment.

Затем добавьте в MainFragment.kt следующий метод:

Этот метод позволяет вам подписаться на наблюдаемое состояние в MainViewModel. Каждый раз, когда состояние dogCount изменяется, приложение передает новое состояние во вью, и с новым состоянием вызывается renderDogCount(), в результате чего пользовательский интерфейс обновляется.

Затем измените onViewCreated(), чтобы подписаться на MainViewModel после вызова суперкласса:

Вам также понадобится логика, которая обновит состояние в MainViewModel. Измените updateDogCount() следующим образом:

Этот метод вызывается всякий раз, когда пользователь обновляет счетчики. Он обновит MainViewModel с новым состоянием. MainViewModel протолкнет это состояние через dogCount, и MainFragment получит уведомление, поскольку он подписан на MainViewModel.

Наконец, в MainFragment удалите onSaveInstanceState(), вызов renderDogCount (dogCount) из onResume() и код saveInstanceState? .Run {…} в onCreate(). Вам это больше не нужно. :)

Скомпилируйте и запустите приложение. Коснитесь счетчиков пару раз и поверните экран. Вы должны увидеть что-то вроде этого:

На приведенном ниже рисунке можно увидеть время жизни ViewModel рядом с соответствующим жизненным циклом действия.

Объекты ViewModel привязаны к Lifecycle, передаваемому ViewModelProvider при получении ViewModel. Он остается в памяти до тех пор, пока Lifecycle, на который он рассчитан, не исчезнет навсегда. В случае активити это происходит, когда она завершена. Для фрагмента это происходит, когда он отсоединяется.

AsynkTask

Загружая или вычисляя что-то в фоне, хорошо бы не только получить результаты, но еще и иметь возможность выводить пользователю информацию о прогрессе. Конечно, все это можно сделать самому с помощью очереди сообщений, но разработчики Android и тут упростили нам жизнь, создав класс AsyncTask.

Класс AsyncTask — это представитель Java-обобщений (generic) в мире Android. У классов-обобщений заранее не определен тип данных, с которыми им предстоит работать. Этот прием позволяет создать класс, который в последующем сможет без проблем работать с любым типом данных. В данном случае благодаря дженерику AsynkTask возможно запускать новые потоки с совершенно произвольными объектами внутри.

C помощью AsyncTask теперь можно почти не думать (о вероятных последствиях позже) о создании потока, а просто создать объект и обрабатывать результаты. К примеру, с помощью AsyncTask удобно преобразовывать файлы (например, их зашифровать), при этом сам метод шифрования может быть объявлен в Activity главного потока.

Помимо , порождающего новый поток, в AsynkTask есть методы, которые будут выполняться уже в главном потоке.

Для запуска нового потока достаточно одной строчки в Activity:

С появлением AsyncTask разработчики обрели практически универсальный инструмент, позволяющий в короткие сроки написать код, генерирующий новые потоки, а потом так же быстро получить в UI результаты вычислений, отслеживая при этом прогресс. Но у этого класса есть несколько неприятных моментов, которые могут сделать приложение совершенно нестабильным.

Переключитесь на SKIA Андроид

Если на вашем телефоне стоит Андроид 7.0 или выше, вы можете, попробовать перевести движок рендеринга графического процессора на SKIA, после чего, по отзывам пользователей, FPS в играх увеличивается. Я попробовал на игре Star Wars: Галактика героев и могу подтвердит, что игра стала плавней. Включить режим SKIA, можно в том же режиме разработчика, а также изменить другие настройки, чтобы ускорить скорость работы Андроида.

Пока вы находитесь в режиме разработчика, можете попробовать включить Force 4x MSAA. Это метод сглаживания, который не увеличит FPS в игре, но может сделать их визуализацию более красивой. Но, увеличит нагрузку на батарею и может привести к определенному замедлению смартфона. Тем не менее, изменение этих настроек не принесут вреда телефону. Попробуйте включить их, сравнит, и выбрать то, что вам больше нравиться.

Понимание обратных вызовов жизненного цикла фрагмента

Теперь вы можете немного глубже погрузиться в каждое событие жизненного цикла, чтобы лучше понять жизненный цикл фрагмента:

  • onCreate(): фрагмент достигает состояния Created. Подобно onCreate() активити, этот колбэк получает Bundle, содержащий любое состояние, ранее сохраненное onSaveInstanceState().
  • onCreateView(): вызывается для расширения или создания вью фрагмента.
  • onViewCreated(): вью фрагмента создается с ненулевым объектом View. Это представление устанавливается для фрагмента и может быть получено с помощью getView().
  • onStart(): фрагмент переходит в состояние Started. В этом состоянии гарантируется, что вью фрагмента доступно и безопасно выполнить FragmentTransaction для дочернего FragmentManager фрагмента.
  • onResumed(): фрагмент переходит в состояние Resumed. Он становится видимым после завершения всех эффектов Animator и Transition. Теперь пользователь может взаимодействовать с фрагментом.
  • onPause(): фрагмент возвращается в состояние Started. ОС вызывает этот колбэк, когда пользователь начинает покидать фрагмент, пока фрагмент все еще виден.
  • onStop(): фрагмент возвращается в состояние Created и больше не отображается.
  • onDestroyView(): запускается после завершения всех анимаций выхода и переходов, когда представление фрагмента было отделено от окна. На этом этапе все ссылки на представление фрагмента должны быть удалены, что позволит очистить представление фрагмента от мусора.
  • onDestroy(): фрагмент переходит в состояние Destroyed. Это происходит при удалении фрагмента или при уничтожении FragmentManager. На этом этапе жизненный цикл фрагмента подошел к концу.

Теперь, когда вы лучше понимаете, что скрывается под капотом, переходите между основным экраном и экраном Share, чтобы увидеть танец жизненного цикла фрагмента. :)

Как вы видели в этом и предыдущем разделе, жизненный цикл Android довольно сложен. Управлять состояниями и взаимодействовать с пользовательским интерфейсом в нужное время может быть непросто для неопытных разработчиков. Это привело к появлению некоторых новых API и компонентов Android, которые должны облегчить жизнь всем разработчикам Android. Одним из таких компонентов является ViewModel.

Как отключить режим разработчика на телефоне

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

Чтобы отключить режим разработчика пройдите по пути:

  1. Войдите в настройки.
  2. Откройте опцию «Система».
  3. Нажмите на «Дополнительно».
  4. Войдите в опцию «Для разработчиков».
  5. Переставьте ползунок настроек работы режима в положение «Отключено».

На большей части телефонов опция режима разработчиков исчезает из параметров телефона, все настройки будут сброшены, и эта функция станет отключенной. На некоторых других устройствах сама функция перестанет работать, но пункт опции «Для разработчиков» остается в настройках смартфона или планшета.

Как очистить кэш на Android

Чтобы убрать функцию для разработчиков устройства используйте способ стирания данных на телефоне. В разных версиях операционной системы Android интерфейс для выполнения необходимых действий может несколько отличаться, но логика действий везде одинакова.

Пройдите последовательные шаги:

  1. Зайдите в «Настройки».
  2. Откройте «Приложения и уведомления».
  3. Нажмите на «Показать все приложения».
  4. Выберите приложение «Настройки».
  1. Войдите в опцию «Хранилище и кеш».
  2. Нажмите на параметр «Очистить хранилище».
  1. В окне с предупреждением нажмите на кнопку «ОК».

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

Существует еще один метод избавиться от режима разработчика: сброс устройства к заводским настройкам. В результате выполнения этой операции, с телефона будет удалена учетная запись Google и все пользовательские данные, сброшены настройки и удалены все установленные приложения, кроме дефолтных. Система будет восстановлена в параметрах по умолчанию, какие она имела при покупке мобильного телефона.

В числе прочих параметров будет удален режим разработчика. Пользоваться этим способом стоит лишь в случае серьезных неполадок в работе программного обеспечения на телефоне.

Понимание роли жизненного цикла приложений

Операционная система (ОС) Android — это многопользовательская система Linux. В большинстве случаев каждое приложение работает в собственном процессе Linux. ОС создает процесс, когда необходимо выполнить любой из компонентов приложения. Когда ни один компонент приложения не запущен, а ОС требуется освободить память для запуска других приложений, процесс прерывается.

ОС Android использует иерархию по важности, чтобы определить, какие процессы оставить в живых или уничтожить. В этой иерархии процессы делятся на разные типы

Этот тип зависит от запущенных в данный момент компонентов приложения и их текущего состояния.

Самый распространенный компонент приложения — Activity. Каждое приложение для Android имеет одно или несколько активити. Когда пользователь перемещается по приложению, действия проходят через разные состояния жизненного цикла.

Разработчики должны понимать, как различные компоненты влияют на время жизни процесса. Неправильное использование этих компонентов может привести к тому, что система остановит процесс, пока выполняет важную работу.

Изучение жизненного цикла фрагмента

Как и у активити, у фрагментов есть свой жизненный цикл. Когда пользователь перемещается по вашему приложению и взаимодействует с ним, ваши фрагменты переходят из одного состояния в другое в своем жизненном цикле, когда они добавляются, удаляются, а также выходят на экран или выходят из него.

На рисунке выше вы можете видеть, что жизненный цикл фрагмента аналогичен жизненному циклу активити, но содержит некоторые дополнительные методы, специфичные для фрагмента. Прежде чем объяснять каждый колбэк, проверьте их в приложении.

В предыдущем разделе вы поиграли с двумя активити и увидели, как меняется их жизненный цикл при перемещении между экранами. В этом примере вы реализуете те же экраны с фрагментами. Вы можете найти два фрагмента, которые представляют каждый экран в пакете фрагментов: MainFragment.kt и ShareFragment.kt. Также есть одна активити контейнера и пакет viewmodels. Пока не обращайте внимания на пакет viewmodels. Он понадобится вам в следующем разделе.

Если вы проверите MainFragment.kt, вы заметите много общего с MainActivity.kt. У них одинаковая логика управления состояниями, но MainFragment.kt содержит еще несколько колбэков жизненного цикла.

Перед запуском приложения откройте SplashActivity.kt и обновите startFirstActivity(), чтобы он запускал ActivityWithFragments вместо MainActivity:

Отлично! Теперь соберите и запустите приложение. Затем осмотрите логи.

Обратите внимание, как жизненный цикл фрагмента синхронизируется с жизненным циклом активности. Сначала приложение создает и запускает ActivityWithFragments

После этого он создает и запускает фрагмент и его просмотр. Наконец, он возобновляет как активити, так и фрагмент.

Далее нажмите назад и снова наблюдайте за логами.

Закрыв приложение, вы запустили процесс уничтожения активити. Как и раньше, события жизненного цикла фрагмента следуют за событиями жизненного цикла активити. И активити, и фрагмент сначала приостанавливаются, затем останавливаются и, наконец, уничтожаются.

Состояние жизненного цикла фрагмента никогда не может быть выше, чем у его родительского. Например, родительский фрагмент или активити должны начинаться до его дочерних фрагментов. Точно так же дочерние фрагменты должны останавливаться до их родительского фрагмента или активности. Из приведенных выше логов можно подумать наоборот — что сначала останавливается действие, но это только потому, что вы распечатываете логи как первый вызов в колбэках жизненного цикла. Внутренне ОС обеспечивает остановку всех дочерних фрагментов перед остановкой активити.

Очистить кеш память Андроид

Кеш — это данные приложений, которые помогают быстрей загружаться — тем самым ускоряя работу Андроид. Браузер может кешировать изображения часто посещаемых вами сайтов, из-за чего ему не нужно загружать их каждый раз, когда вы заходите на такие сайты.

Кешированные данные должны делать телефон быстрей. Но они могут также и негативно влиять на скорость Андроид, если кеш становиться раздутым (не говоря уже о том, что он пожирает место на устройстве). У тех приложений, где кеш стал неприемлемо большим, его можно удалить, зайдя в «Настройки» → «Приложения» → выберите приложение → «Память» → «Очистить кеш».

Заметка: Подробнее о том, как и когда, очищать кеш на телефонах Андроид, вы можете узнать на странице: Как очистить кэш на Андроиде.

Если вы не ходите или боитесь в ручную чистить кеш, может воспользоваться специальным приложением, например CCleaner.

Developer:

Price:
To be announced

Понимание колбэков жизненного цикла активити

Вы только что прошли один полный жизненный цикл активити: активити была создана, возобновлена и окончательно уничтожена, когда вы вышли из приложения.

На приведенной выше диаграмме представлен жизненный цикл активити:

  • onCreate(): активити переходит в состояние Создано. Здесь вы выполняете логику, которая должна выполняться только один раз за все время активити. Сюда можно включить настройку контент вью, связывание активити с ViewModel, создание экземпляров некоторых переменных области класса и т.д.
  • onStart(): активити переходит в состояние Начато. Этот вызов делает активити видимой для пользователя, поскольку приложение готовится к тому, чтобы активити перешла на передний план и стала интерактивной.
  • onResume(): активити переходит в состояние Возобновлено. Теперь пользователь может взаимодействовать с активити. Здесь вы можете включить любую функциональность, которая должна работать, пока компонент виден и находится на переднем плане.
  • onPause(): активити переходит в состояние Приостановлено. Этот вызов указывает на то, что активити больше не находится на переднем плане, хотя она может быть видна, например, если пользователь находится в многооконном режиме. В это время вам следует приостановить или настроить операции, которые не должны продолжаться или должны продолжаться в модерации. Действие остается в этом состоянии до возобновления активити, например, открытия или закрытия нижнего листа в действии, или до тех пор, пока оно не станет полностью невидимым для пользователя, например, при открытии другого действия.
  • onStop(): активити переходит в состояние Остановлено. Активити больше не видна пользователю. Здесь вы должны освободить или настроить ресурсы, которые не нужны, пока активити не видна пользователю. Вы также должны использовать эту возможность для выполнения операций выключения для задач, которые относительно интенсивно загружают процессор, например, для операций с базой данных.
  • onDestroy(): активити переходит в состояние Уничтожено. На этом работа заканчивается. Это может быть потому, что:
  • Пользователь полностью закрывает активити.
  • finish() вызывается для активити.
  • Система временно прерывает активити из-за изменения конфигурации, например поворота устройства или многооконного режима.

Бывают ситуации, когда система убивает процесс, следовательно, не вызывает onDestroy() или любые другие методы жизненного цикла активити. Таким образом, его не следует использовать для того, чтобы делать те вещи, которые должны остаться после завершения процесса.

Процессы и потоки

Прежде чем разбираться с Android API, вспомним, какой структурой обладает эта ОС. В ее основе лежит Linux-ядро, в котором реализованы базовые механизмы, присущие всем *nix-системам. В ядре собраны модули, предназначенные для низкоуровневой работы: взаимодействия с железом, организации памяти, файловой системы и так далее.

В мире Linux каждая запущенная программа — это отдельный процесс. Каждый процесс обладает уникальным номером и собственной «территорией» — виртуальным адресным пространством, в рамках которого содержатся все данные процесса. Поток же — это набор инструкций внутри запущенной программы (процесса), который может быть выполнен отдельно. У потока нет своего уникального идентификатора и адресного пространства — все это он наследует от родительского процесса и делит с другими потоками.

Массовое распространение в Google Play приложений, имеющих проблемы с утечкой памяти, резонно вызовет у пользователей ощущение, что «Android тормозит»
Рис. 1. Список активных процессов в Android
Другие статьи в выпуске:

Xakep #208. Атака на сигналку

  • Содержание выпуска
  • Подписка на «Хакер»-60%

Такое положение дел приводит к тому, что со стороны неизвестно, как протекает жизнь внутри процесса, есть ли там потоки и сколько их, — для ОС и других процессов это атомарная структура с уникальным идентификатором. Поэтому ОС может манипулировать лишь процессом, а управляет потоками только породивший их процесс. Вообще, внутренний мир операционных систем очень интересен, поэтому советую читателям почитать что-нибудь из классической литературы по Linux.

Когда в компьютерах (а вслед за ними — в планшетах и телефонах) появились процессоры с несколькими ядрами, программисты внедрили в ОС планировщик задач. Такой планировщик самостоятельно распределяет нагрузку по всем ядрам процессора, исполняя блоки кода параллельно или асинхронно, и тем самым повышает производительность. Поначалу маркетологи даже продавали компьютеры с лозунгом «Два ядра — в два раза быстрее», но, к сожалению, действительности он не соответствует.

В Android программист обязан повсеместно создавать новые потоки и процессы. Все операции, которые могут продлиться более нескольких секунд, должны обязательно выполняться в отдельных потоках. Иначе начнутся задержки в отрисовке интерфейса и пользователю будет казаться, что приложение «зависает».

Вообще, суть многопоточного программирования в том, чтобы максимально задействовать все ресурсы устройства, при этом синхронизируя результаты вычислений. Это не так легко, как может показаться на первый взгляд, но создатели Android добавили в API несколько полезных классов, которые сильно упростили жизнь Java-разработчику.

Рейтинг
( Пока оценок нет )
Editor
Editor/ автор статьи

Давно интересуюсь темой. Мне нравится писать о том, в чём разбираюсь.

Понравилась статья? Поделиться с друзьями:
Союз-Маркет
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: