Стили и темы. Ресурсы. Фигуры. Обработчики событий. Содержание Проект погода (начало): геолокация, http(s)-запросы, разбор json, ImageView.
# Ориентация экрана, жизненный цикл activity, сохранение данных ## Ориентация экрана >Взято [отсюда](http://developer.alexanderklimov.ru/android/orientation.php#whereorientation) При разработке мобильных приложений со сложным дизайном нередки ситуации, когда при изменении ориентации экрана все выглядит совсем не так, как Вам хотелось бы. В таких случаях выходом из ситуации может стать использование различных шаблонов для книжной и альбомной ориентации устройства. При этом переключение между шаблонами может осуществляться в автоматическом или динамическом (ручном) режиме. Для автоматического режима достаточно создать дополнительнай файл шаблона для альбомной ориентации. Создадим дополнительный шаблон с "инженерной" версией калькулятора: ![](../img/calc_landscape.jpeg) Для этого добавим **одноименный** шаблон, указав ему ориентацию: ![](../img/layout_orientation.png) ![](../img/layout_orientation2.png) **Android Studio** автоматически создаст каталог `layout-land` и сохранит туда новый шаблон. Когда вы создаёте альтернативную разметку, то не забывайте проверять наличие элементов, к которым будете обращаться программно, иначе получите ошибку. ## Жизненный цикл *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") ?: "" } ```
Стили и темы. Ресурсы. Фигуры. Обработчики событий. Содержание Проект погода (начало): геолокация, http(s)-запросы, разбор json, ImageView.