it-notepad.com

Android Pro Kotlin. Глава 3. Активности Android. Часть 2

Оглавление

Android Pro Kotlin. Глава 3. Активности Android. Часть 1

Системные фильтры намерений

Жизненный цикл Активности Android

Сохраняем состояние активности между перезапусками

Системные фильтры намерений

Системные приложения, т.е. приложения которые уже были установлены на Вашем приложении до момента покупки, имеют свои фильтры намерений, которые Вы можете использовать в своем приложении, для их вызова. К сожалению, не всегда можно сразу отгадать, какой неявный запрос намерения необходимо использовать для их вызова. В случае если нет возможности найти документацию в интернете, единственный возможный вариант – это реверс инжиниринг системных файлов APK . Но начиная с  API 26, Вы можете найти всю информацию на официальном сайте с Android документацией в разделе “The System Intent Filters“.

Рассмотрим пример. Например Вы хотите реализовать функционал отправки электронного письма и чтобы не тратить месяцы на внедрение функционала, который будет весьма редко использоваться Вашими пользователями, отправим намерение системному почтовому приложению с действием по отправке электронного письма. Если посмотреть на таблицу вариантов фильтра намерений для системного приложения PrebuiltGmail, можно немного запутаться. Интерфейс общего назначения не должен быть слишком запутанным и иметь много входных параметров. Во вторых надо посмотреть на имена действий, чтобы найти то, которое нам подходит больше всего. Многообещающим кандидатом является действие “SEND_TO” – ему необходимо передать всего лишь параметр “mailto:“. И это именно тот параметр, который нам нужен. Используя URI вида "mailto:...” можно указывать имена получаталей, имена получателей копии или скрытых получателей, тему и даже тело письма. Однако Вы также можете использовать URI типа “mailto:timur@it-notepad.com” и добавлять получателей, тело и тему письма через дополнительные поля. Таким образом можно отправить письмо, используя почтовые приложения, установленные на устройстве. Например:

val emailIntent:Intent = Intent(Intent.ACTION_SENDTO,      
Uri.fromParts("mailto","abc@gmail.com", null))  
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Subject")  
emailIntent.putExtra(Intent.EXTRA_TEXT, "Body")  
startActivity(Intent.createChooser(emailIntent, "Send email..."))  
// or startActivity(emailIntent) if you want to use  
// the standard chooser (or none, if there is only  
// one possible receiver).

Осторожно То, как именно обрабатывается URI сторонним приложением, остается на усмотрение установленного приложения. Плохо спроектированная программа может вообще не позволять указывать данные заголовка электронной почты.  Для того, чтобы быть уверенным в правильности обработки входящего намерения, Вы можете например, указывать тему, тело(в применении к разговору о приложении для электронной почты) в качестве дополнительных полей намерения.


Жизненный цикл активности

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

Возможные состояния активности и переходы между ними приведены в таблице 3.1

 

От состояния К состоянию Описание Обратный вызов
Завершено Создано Активность вызывается первый раз или после уничтожения onCreate() – подготовка UI и старт сервисов
Создано Запущено Активность запускается после создания onStart() – здесь можно запускать службы, которые нужны только в том случае, когда активность видна
Запущено Возобновлено Состояние Возобновлено следует автоматически после состояния Запущена onResume()
Возобновлено Работает Состояние Работает автоматически следует за состоянием Возобновлено Активность видна и функционирует для работы с пользователем
Работает Пауза Активность теряет фокус, потому что пользователь нажал кнопку Назад или Недавние onPause()
Пауза Возобновлено Активность не остановлена и пользователь возвращается к активности onResume()
Пауза Остановлено Активность больше не видна пользователю, например потому что запускается другая активность onStop() Вы можете остановить сервисы, которые больше не нужны если активность больше не видна.
Остановлено Запущено Остановленная активность запущена снова onStart() Вы можете снова запустить сервисы, которые нужны если активность становится видимой.
Остановлено Уничтожено Остановленная активность удалена onDestroy() Освободите все ресурсы, выполните очистку и остановите сервисы, которые были запущены в методу onCreate()
Таблица 3.1 Переходы между состояниями активности
Рис. 3.1 Жизненный цикл Android активности

Сохраняем состояние активности между перезапусками

Мы уже вскользь упоминали эту тему раньше, про сохранение состояние активности между перезапусками. И не важно из за чего это происходит – из за поворота устройства или из за принудительной остановки активности –  ОС Android. Здесь мы рассказываем подробнее про этот процесс. 

Глядя на жизненный цикл активности – мы видим, что активность уничтожается после выполнения метода onStop. В жизненном цикле активности есть еще 2 метода, о которых мы не упомянули –  onSaveInstanceState() и onRestoreInstanceState(). Они вызываются каждый раз, когда Android решает, что активность должна быть сохранена или восстановлена. Это не то же самое что вызовы onStart() и onStop() – потому что в них не всегда имеет смысл сохранять состояние активности. Например если активность не была уничтожена, а просто приостановлена, состояние будет сохранено, и методы onSaveInstanceState() и onRestoreInstanceState() вызываться не будут. 

Что касается перезапуска активности – Android нам в этом плане здорово помогает – стандартные реализации вызовов onSaveInstanceState() и onRestoreInstanceState() сохраняют и восстанавливают элементы пользовательского интерфейса, имеющие ID идентификатор. Если это все, что Вам нужно, больше ни о чем беспокоиться не надо. Если у Вас сложная активность, содержащая поля, ползунки и прогресс – здесь уже необходимо самому заниматься сохранением значений UI. В этом случае Вам необходимо переопределить методы обратного вызова onSaveInstanceState() и onRestoreInstanceState(). И убедиться что Вы вызываете в них одноименные методы суперкласса:

override fun onSaveInstanceState(outState:Bundle?) {    
    super.onSaveInstanceState(outState)    
    // add your own data to the Bundle here...    
    // you can use one of the put* methods here    
    // or write your own Parcelable types
}

override fun onRestoreInstanceState(savedInstanceState: Bundle?) {
    super.onRestoreInstanceState(savedInstanceState)
    // restore your own data from the Bundle here...
    // use one of the get* methods here
}

Обратите внимание на тот факт, что сохраненное состояние также передается обратному методу onCreate(), так что это уже ваше решение, где вы хотите восстанавливать данные – в методе onRestoreInstanceState() или onCreate().

Не во всех ситуация механизм сохранения состояний может Вам подойти. Например, Вы не можете сохранить данные, если после вызова onStop() последует вызов onDestroy(). В этом случае метод onSaveInstanceState() не будет вызван.  Если Вы хотите сохранить состояние при уничтожении приложения, Вы можете реализовать сохранение данных в методе onDestroy(), записав все данные в хранилище настроек или в базу данных(поставщик контента), и затем прочитать их снова в метода обратного вызова onCreate(). См. раздел Базы данных, глава 8. 

 
 
 

 
 
 
Exit mobile version