# 6.1. Жизненный цикл Activity
====
---
# План занятия
1. Что такое активити?
1. Состояния активити.
1. Основные методы жизненного цикла.
1. Редко используемые методы жизненного цикла.
1. Взаимодействия с кнопками.
1. Сохранение состояния.
2. Переход между Activity
3. Действия при переходах между Activity
4. Стек вызовов
---
# Вспоминаем прошлые занятия
- Чем отличаются внутренние и внешние файлы?
- Какие разрешения нужны для работы с файлами?
- Какие операции можно производить с файлами?
---
# Что такое активити
**Активити** — это один из системных компонентов ОС Андроид, и, как и у любого другого компонента, ее **главная функция — позволить приложению взаимодействовать с системой.**
Два основных сценария взаимодействия с системой:
- точка входа в приложение,
- взаимодействие с системой контроля памяти, при которой ОС закрывает наименее приоритетные активити при нехватке оперативной памяти.
**Второстепенная функция — показ интерфейса.** В современной разработке предпочтительно использовать принцип приложений с одной активити и строить навигацию и основную часть UI с помощью фрагментов.
Отдельные активити используются как точки входа, например, для Dynamic Feature Modules. (https://www.youtube.com/watch?v=httqEshs_Bk)
---
# Четыре состояния активити
## 1. Не существует
Либо активити еще не была создана, либо была уничтожена с помощью вызова `finish()`, либо была уничтожена системой.
---
## 2. Выполняется (Resumed)
Активити показывается на экране и готова к взаимодействию с пользователем.
Из этого состояния она может перейти только в состояние Приостановлена (Paused).
---
## 3. Приостановлена (Paused)
Активити показывается на экране, но она не в фокусе. Над ней есть какой-то элемент, с которым происходит взаимодействие, либо она в процессе полного скрывания с экрана. В этом случае Paused является переходным состоянием и сразу за ним следует состояние Stopped.
В этом состоянии активити существует и все ее процессы продолжаются в фоне.
Из этого состояния она может перейти в состояния Выполняется (Resumed) или Остановлена (Stopped).
---
## 4. Остановлена (Stopped)
Активити все еще существует, но больше не видна.
В этом состоянии при нехватке ресурсов система может уничтожить эту активити.
Из этого состояния она может перейти в состояния Приостановлена (Paused) или Не существует.
---
# Основные методы жизненного цикла
Важно вызывать методы super-класса при их переопределении. Например, `super.onStart();`.
---
## onCreate()
Первая точка взаимодействия с активити. Система вызывает этот метод, когда создает объект активити.
Тут нужно производить единоразовые настройки, которые будут сохраняться на протяжении всего существования активити, например, устанавливать файл интерфейса методом `Activity.setContentView()`.
После выполнения этого метода активити находится в состоянии Остановлена (Stopped).
---
## onStart()
Система вызывает этот метод перед тем, как активити покажется на экране. Вызывается при первом запуске приложения и при перезапусках.
Тут нужно включать механизмы, которые работают только во время отображения интерфейса, например, подписываться на системные события (Broadcast).
После исполнения этого метода активити находится в состоянии Paused.
---
## onResume()
Этот метод вызывается перед тем, как активити получит фокус.
Основное отличие от onStart - если активити теряет фокус, а потом возвращает его, onResume будет вызван, а onStart - нет.
После исполнения этого метода активити находится в состоянии Выполняется (Resumed).
---
## onPause()
Зеркальный к onResume метод. Вызывается, когда активити теряет фокус.
Тут нужно отменить все то, что включалось в onResume(), также тут принято останавливать анимации и вычисления, связанные с пользовательским интерфейсом.
Важно сделать работу в этом методе быстро, чтобы не задерживать отображение интерфейса следующего экрана.
После исполнения этого метода активити находится в состоянии Приостановлена (Paused).
---
## onStop()
Зеркальный метод для onStart. Вызывается, когда активити перестает отображаться.
Тут нужно отменить все то, что включалось в onStart(). В этом методе принято сохранять данные. Допустимо, что он будет выполняться чуть дольше, чем onPause().
После исполнения этого метода активити находится в состоянии Остановлена (Stopped).
---
## Уничтожение Activity системой
Activity уничтожается в двух случаях:
1. когда для неё вызывается метод finish();
2. когда не хватает памяти на новые и работающие activity, удаляются неактивные activity из стека.
После возвращения метода onStop() (если мы говорим о версиях Android до Honeycomb, 3.0, то это может произойти после возвращения onPause()) система может уничтожить активити или процесс приложения для освобождения памяти.
- В случае уничтожения Activity будет вызван onDestroy().
- В случае уничтожения процесса ничего более вызвано не будет.
После этого активити перестает существовать.
---
## onDestroy()
Зеркальный метод для onCreate. Вызывается, когда активити уничтожается.
Используется редко, так как его вызов не гарантирован.
Нужно понимать специфику создания и уничтожения процессов для правильного использования этого метода.
---
## Отрезки жизненного цикла
На основе состояний можно выделить отрезки жизненного цикла активити:
- вce время существования (entire lifetime) - от onCreate до onDestroy.
- видимое время (visible lifetime) - от onStart до onStop, таких отрезков может быть несколько за все время существования.
- время в фокусе (foreground lifetime) - от onResume до onPause, таких отрезков может быть несколько за видимое время.
---
## Дополнительный метод onRestart()
Метод добавлен для удобства, вызывается перед вторым и последующими вызовами onStart(), то есть перед перезапуском приложения.
---
## Диаграмма
Наглядная иллюстрация методов жизненного цикла:

---
## Пример
1. Пользователь нажимает на иконку приложения
```
onCreate()
onStart()
onResume()
```
2. Приходит нотификация другого приложения и отображается поверх Activity
`onPause()`
3. Пользователь сбрасывает нотификацию и возвращается в приложение
`onResume()`
4. Пользователь нажимает кнопку домой - активити сворачивается и больше не видна
```
onPause()
onStop()
```
5. Пользователь нажимает на иконку приложения
```
onStart()
onResume()
```
6. Пользователь нажимает кнопку назад
```
onPause()
onStop()
onDestroy()
```
---
# Редко используемые методы жизненного цикла
## onPostCreate()
Вызывается, когда активити окончательно создана, то есть методы `onStart()` и `onRestoreInstanceState()` были вызваны и выполнены.
---
## onPostResume()
Вызывается после `onResume()`.
---
# Взаимодействия с кнопками
## onKeyDown()
Если пользователь нажимает кнопку, и она не обрабатывается `View`, имеющим фокус, вызывается этот метод. По умолчанию при нажатии кнопки назад будет вызван метод `onBackPressed()`.
---
## onKeyLongPress()
Вызывается при долгом нажатии на кнопку, если `onKeyDown()` прежде вернул `true`.
---
## onBackPressed()
Метод для обработки нажатия кнопки назад. Реализация по умолчанию выполняет переход назад, так что если требуется сохранить эту логику, то нужно вызвать `super.onBackPressed();`
---
# Сохранение состояния
Система может уничтожить активити при нехватке памяти, это один из основных принципов работы операционной системы Android. Чтобы пользователь не потерял данные, нужно предпринять несколько шагов для их сохранения и восстановления.
Для тестирования этого механизма удобно использовать режим «Don't keep activities» в настройках разработчика.
---
## onSaveInstanceState(Bundle)
Вызывается перед тем, как активити уничтожается системой. В параметр Bundle можно сохранять информацию, которая должна пережить пересоздание активити.
Этот метод вызывается перед onStop() (В версиях до 3.0 он вызывался до onPause()).
Если пользователь инициирует уничтожение активити, например, с помощью кнопки назад, этот метод вызван не будет.
По умолчанию восстанавливает состояние всех View с помощью `View.onSaveInstanceState()`, так что всегда стоит вызывать super-метод.
Но, например, TextView не восстановит текст, если не установлен атрибут `android:freezesText`.
---
## onRestoreInstanceState(Bundle)
Вызывается, только если прежде был вызван `onSaveInstanceState`. В этом методе нужно получить информацию из `Bundle` и на ее основе восстановить состояние активити.
---
## Bundle в onCreate(Bundle)
Другой вариант - тот же `Bundle` будет доступен при вызове `onCreate`.
`Bundle` будет равен `null`, если `onSaveInstanceState` не был вызван ранее, например, при первом запуске активити.
---
---
## Переходы между Activity
Как можно увидеть на `диаграмме` — у Activity жизненный цикл включает в себя не только события во время отображения экрана, но и при переходе на другой экран.
Для перехода между Activity можно использовать 2 метода:
1. StartActivity — запускает новую Activity, если не нужно получить из неё данные;
2. startActivityForResult() — запускает новую Activity и возвращает результат выполнения в то, которая вызывала.
---
## Примеры запуска
Простой запуск:
```
Intent intent = new Intent(this, SignInActivity.class);
startActivity(intent);
```
Запуск с ожиданием результата:
```
startActivityForResult(
new Intent(Intent.ACTION_PICK,
new Uri("content://contacts")),
PICK_CONTACT_REQUEST);
```
---
## При вызове новой Activity
При переходе от одной Activity к другой, они обе получают изменение событий жизненного цикла. Так, в вызывающей Activity будет вызвано действие onPause, а в создаваемой Activity будет вызвано onCreate.
В данном случае нужно с осторожностью обрабатывать ресурсы, которые задействуются в этих методах. Например, если в onPause вызывающей и в onCreate вызываемой Activity будет производиться запись одного и того же файла, это может привести к конфликтам. Скорее процесс запуска второй Activity пересекается с процессом остановки первой.
Порядок действия при вызове Activity B из Activity A:
1. Выполняется метод onPause() activity А.
2. Методы onCreate(), onStart() и onResume() activity B выполняются последовательно. (Activity B отображается пользователю).
3. Затем, если activity A больше не отображается на экране, выполняется его метод onStop().
---
## Стек переходов
* Когда текущая activity запускает другую, новая activity помещается в вершину стека и получает фокус.
* Предыдущая activity остается в стеке, но ее выполнение останавливается. Когда activity останавливается, система сохраняет текущее состояние ее пользовательского интерфейса.
* Когда пользователь нажимает кнопку Назад, текущая activity удаляется из вершины стека (activity уничтожается) и возобновляется работа предыдущей activity (восстанавливается предыдущее состояние ее пользовательского интерфейса).
Аctivity в стеке никогда не переупорядочиваются, только добавляются в стек и удаляются из него — добавляются в стек при запуске текущей activity и удаляются, когда пользователь выходит из нее с помощью кнопки Назад.
По существу, стек переходов назад работает по принципу «последним вошел — первым вышел». На рисунке это поведение показано на временной шкале: состояние activity и текущее состояние стека переходов назад показано в каждый момент времени.

---
## Стек переходов
Если пользователь продолжает нажимать кнопку Назад, activity поочередно удаляются из стека, открывая предыдущую activity, пока пользователь не вернется на главный экран (или в activity, которая была запущена в начале выполнения задачи). Когда все операции удалены из стека, задача прекращает существование.
Задача — это совокупность activity приложения.
В стандартной ситуации, каждое приложение имеет свою задачу и свой стек. При сворачивании приложения, задача уходит в background, но не умирает. Он хранит весь свой стек и при очередном открытии приложения через менеджер или через launcher, существующая задача восстановится и продолжит свою работу.

Две задачи: Задача B взаимодействует с пользователем на переднем плане, тогда как Задача A находится в фоновом режиме, ожидая возобновления.
---
## Заполнение стека
* Когда activity A запускает activity B, activity A останавливается, но система сохраняет ее состояние (например, положение прокрутки и текст, введенный в формы). Если пользователь нажимает кнопку Назад в activity B, activity A возобновляет работу из сохраненного состояния.
* Когда пользователь выходит из задачи нажатием кнопки Домой, текущая activity останавливается и ее задача переводится в фоновый режим. Система сохраняет состояние каждой activity в задаче. Если пользователь впоследствии возобновляет задачу, выбирая значок запуска задачи, она переводится на передний план и возобновляет activity на вершине стека.
* Если пользователь нажимает кнопку Назад, текущая activity удаляется из стека и уничтожается. Возобновляется предыдущая activity в стеке. Когда activity уничтожается, система не сохраняет состояние операции.
* Можно создавать несколько экземпляров activity, даже из других задач.
---
## Сохранение состояния
Как говорилось выше, система по умолчанию сохраняет состояние activity, когда она останавливается. Таким образом, когда пользователи возвращаются обратно в предыдущую activity, восстанавливается ее пользовательский интерфейс в момент остановки. Однако вы можете — и должны — сохранять состояние ваших activity посредством методов обратного вызова на случай уничтожения activity и необходимости ее повторного создания.
Когда система останавливает одну из ваших activity (например, когда запускается новая activity или задача перемещается в фоновый режим), система может полностью уничтожить эту activity, если необходимо восстановить память системы. Когда это происходит, информация о состоянии activity теряется.
Если это происходит, система знает, что activity находится в стеке переходов назад, но, когда activity переходит на вершину стека, система должна создать ее повторно (а не возобновить ее). Чтобы избежать потери работы пользователя, необходимо сохранять все данные, с которыми работает пользователь в переопределении метода onSaveInstanceState() в вашей activity.
# Что мы узнали
1. Тонкости активити, как система использует активити для организации памяти.
1. Методы жизненного цикла, как ими пользоваться.
1. Восстановление состояния активити после ее уничтожения системой.
1. При переходе от одной activity к другой вызываются последовательно onPause, onCreate, onStart, onResume
2. При переходе от одной activity к другой, первая становится неактивной и сохраняется в стеке переходов, сверху добавляется активная, созданная activity
3. При нажатии на кнопку Домой система сохраняет состояние всех activity задачи (приложения)
4. При нажатии на кнопку Назад, система вытаскивает из стека переходов activity и отображает их
5. При переходе на новые activity нужно сохранять данные с предыдущих activity, т.к. они могут быть уничтожены системой.
---
# Спасибо за внимание! Время задавать вопросы 🙂