Евгений Колесников 3 ani în urmă
părinte
comite
c854b090c6
4 a modificat fișierele cu 71 adăugiri și 2 ștergeri
  1. 70 1
      articles/layout_orientation.md
  2. BIN
      img/activitystates.png
  3. BIN
      img/life_cycle.png
  4. 1 1
      readme.md

+ 70 - 1
articles/layout_orientation.md

@@ -6,7 +6,9 @@
 <a href="../articles/weather.md">Проект погода (начало): геолокация, http(s)-запросы, разбор json, ImageView.
 </a></td><tr></table>
 
-# Ориентация экрана
+# Ориентация экрана, жизненный цикл activity, сохранение данных
+
+## Ориентация экрана
 
 >Взято [отсюда](http://developer.alexanderklimov.ru/android/orientation.php#whereorientation)
 
@@ -27,6 +29,73 @@
 
 Когда вы создаёте альтернативную разметку, то не забывайте проверять наличие элементов, к которым будете обращаться программно, иначе получите ошибку.
 
+## Жизненный цикл *activity*
+
+>http://developer.alexanderklimov.ru/android/theory/activity_methods.php
+
+Все приложения Android имеют строго определенный системой **жизненный цикл**. При запуске пользователем приложения система даёт этому приложению высокий приоритет. Каждое приложение запускается в виде отдельного процесса, что позволяет системе давать одним процессам более высокой приоритет, в отличие от других. Благодаря этому, например, при работе с одними приложениями Android позволяет не блокировать входящие звонки. После прекращения работы с приложением, система освобождает все связанные с ним ресурсы и переводит приложение в разряд низкоприоритетного и закрывает его.
+
+Все объекты *activity*, которые есть в приложении, управляются системой в виде стека *activity*, который называется **back stack**. При запуске новой *activity* она помещается поверх стека и выводится на экран устройства, пока не появится новая *activity*. Когда текущая activity заканчивает свою работу (например, пользователь уходит из приложения), то она удаляется из стека, и возобновляет работу та activity, которая ранее была второй в стеке.
+
+После запуска *activity* проходит через ряд событий, которые обрабатываются системой и для обработки которых существует ряд обратных вызовов:
+
+```
+protected void onCreate(Bundle saveInstanceState);
+protected void onStart();
+protected void onRestart();
+protected void onResume();
+protected void onPause();
+protected void onStop();
+protected void onDestroy();
+```
+
+Схематично взаимосвязь между всеми этими обратными вызовами можно представить следующим образом
+
+![жизненный цикл](../img/life_cycle.png)
+
+Cледует отметить, что при изменении ориентации экрана (и не только) система завершает *activity* и затем создает ее заново, вызывая метод onCreate.
+
+В целом переход между состояниями activity можно выразить следующей схемой:
+
+![жизненный цикл](../img/activitystates.png)
+
+Расмотрим несколько ситуаций. Если мы работаем с *Activity* и затем переключаемся на другое приложение, либо нажимаем на кнопку **Home**, то у *Activity* вызывается следующая цепочка методов: **onPause -> onStop**. *Activity* оказывается в состоянии **Stopped**. Если пользователь решит вернуться к *Activity*, то вызывается следующая цепочка методов: **onRestart -> onStart -> onResume**.
+
+Другая ситуация, если пользователь нажимает на кнопку **Back (Назад)**, то вызывается следующая цепочка **onPause -> onStop -> onDestroy**. В результате *Activity* уничтожается. Если мы вдруг захотим вернуться к *Activity* через диспетчер задач или заново открыв приложение, то *activity* будет заново пересоздаваться через методы **onCreate -> onStart -> onResume**
+
+## Сохранение состояния приложения
+
+Выше был рассмотрен обычный жизненный цикл *Activity* в приложении на Android. Но есть еще два метода, которые вызываются при принудительном закрытии activity (например, при повороте экрана). Перед завершением работы вызывается метод **onSaveInstanceState**, который сохраняет состояние *Actiity*, а после создания *Activity* вызывается метод **onRestoreInstanceState**, который восстанавливает ее состояние. Оба этих метода в качестве параметра принимают объект **Bundle**, который как раз и хранит состояние *activity*:
+
+```java
+protected void onRestoreInstanceState(Bundle saveInstanceState);
+protected void onSaveInstanceState(Bundle saveInstanceState);
+```
+
+Когда система завершает *activity* в принудительном порядке, чтобы освободить ресурсы для других приложений, пользователь может снова вызвать эту *activity* с сохранённым предыдущим состоянием. Чтобы зафиксировать состояние *activity* перед её уничтожением, в классе активности необходимо реализовать метод **onSaveinstancestate()**.
+
+Сам метод вызывается прямо перед методом **onPause()**. Он предоставляет возможность сохранять состояние пользовательского интерфейса активности в объект **Bundle**, который потом будет передаваться в методы **onCreate()** и **onRestoreInstanceState()**. В объект **Bundle** можно записать параметры, динамическое состояние активности как пары "ключ-значение". Когда *activity* будет снова вызвана, объект Bundle передаётся системой в качестве параметра в методы **onCreate()** и **onRestoreInstanceState()**, которые вызываются после **onStart()**, чтобы один из них или они оба могли установить *activity* в предыдущее состояние. Прежде чем передавать изменённый параметр **Bundle** в обработчик родительского класса, сохраните значения с помощью методов **putXXX()** и восстановите с помощью **getXXX()**.
+
+В отличие от базовых методов, методы **onSaveInstanceState()** и **onRestoreInstanceState()** не относятся к методам жизненного цикла *activity*. Система будет вызывать их не во всех случаях. Например, Android вызывает **onSaveinstancestate()** прежде, чем *activity* становится уязвимой к уничтожению системой, но не вызывает его, когда экземпляр *activity* разрушается пользовательским действием (при нажатии клавиши BACK). В этом случае нет никаких причин для сохранения состояния активности.
+
+Метод **onSaveInstanceState()** вызывается системой в случае изменения конфигурации устройства в процессе выполнения приложения (например, при вращении устройства пользователем или выдвижении физической клавиатуры устройства.
+
+Поскольку метод **onSaveinstanceState()** вызывается не во всех случаях, его необходимо использовать только для сохранения промежуточного состояния активности. Для сохранения данных лучше использовать метод **onPause()**.
+
+```kt
+var buffer = ""
+
+override fun onSaveInstanceState(outState: Bundle, outPersistentState: PersistableBundle) {
+    outState.putString("buffer", buffer)
+    super.onSaveInstanceState(outState, outPersistentState)
+}
+
+override fun onRestoreInstanceState(savedInstanceState: Bundle) {
+    super.onRestoreInstanceState(savedInstanceState)
+    buffer = savedInstanceState.getString("buffer") ?: ""
+}
+```
+
 <table style="width: 100%;"><tr><td style="width: 40%;">
 <a href="../articles/themes.md">Стили и темы. Ресурсы. Фигуры. Обработчики событий.
 </a></td><td style="width: 20%;">

BIN
img/activitystates.png


BIN
img/life_cycle.png


+ 1 - 1
readme.md

@@ -376,7 +376,7 @@ ERD,
 
 1. [Стили и темы. Ресурсы. Фигуры. Обработчики событий.](./articles/themes.md)
 
-1. [Смена ориентации](./articles/layout_orientation.md)
+1. [Смена ориентации, жизненный цикл activity, сохранение данных](./articles/layout_orientation.md)
 
 1. [Проект погода (начало): геолокация, http(s)-запросы, разбор json, ImageView.](./articles/weather.md)