- Activity (Активность, Деятельность)
- Что такое Activity
- Жизненный цикл активности
- Активность в виде диалогового окна
- Програмнное создание активности
- Классы Activity в Android
- Activity
- Activity и жизненный цикл приложения
- Жизненный цикл приложения
- onCreate()
- onStart
- onResume
- onPause
- onStop
- onDestroy
- Управление жизненным циклом
- Understanding the Android Application Class
Activity (Активность, Деятельность)
Что такое Activity
Термин Activity еще не устоялся в русском языке у разработчиков. Некоторые используют слово Активность, другие — Деятельность. Чтобы не путаться в названиях, я буду использовать термин Активность (смотри примечание).
Разработчики со стажем могут воспринимать Активность как форму. Простые приложения состоят из одной активности. Более сложные приложения могут иметь несколько окон, т.е. они состоят из нескольких активностей, которыми надо уметь управлять и которые могут взаимодействовать между собой.
Активность, которая запускается первой, считается главной. Из нее можно запустить другую активность. Причем не только ту, которая относится к нашему приложению, но и другого приложения. Пользователю будет казаться, что все запускаемые им активности являются частями одного приложения, хотя на самом деле они могут быть определены в разных приложениях и работают в разных процессах. Попробуйте воспринимать активности как страницы разных сайтов, открываемых в браузерах по ссылке.
Обычно активность занимает весь экран устройства, но это не является обязательным требованием. Вы можете создавать полупрозрачные и плавающие окна активностей. И с развитием Android такой подход набирает обороты.
Чтобы создать активность, нужно унаследоваться от класса Activity и вызвать метод onCreate(). В результате мы получим пустой экран. Толку от такого экрана никакого. Поэтому в активность добавляют компоненты, фрагменты с помощью разметки.
Жизненный цикл активности
Активность имеет жизненный цикл — начало, когда Android создает экземпляр активности, промежуточное состояние, и конец, когда экземпляр уничтожается системой и освобождает ресурсы. Активность может находиться в трех состояниях:
- активная (active или running) — активность находится на переднем плане экрана. Пользователь может взаимодействовать с активным окном;
- приостановленная (paused) — активность потеряла фокус, но все еще видима пользователю. То есть активность находится сверху и частично перекрывает данную активность. Приостановленная активность может быть уничтожена системой в критических ситуациях при нехватке памяти;
- остановленная (stopped) — если данная активность полностью закрыта другой активностью. Она больше не видима пользователю и может быть уничтожена системой, если память необходима для более важного процесса.
Если активность, которая была уничтожена системой, нужно снова показать на экране, она должна быть полностью перезапущена и восстановлена в своем предыдущем состоянии.
Активность в виде диалогового окна
Помните, изучая темы, мы создали вторую активность в виде диалогового окна. С таким же успехом вы можете создать окно и для основной активности. Добавим в манифесте для активности строчку:
Напишем код для запуска:
Обратите внимание, что в данном примере мы не используем разметку, а программно создаём экземпляр класса TextView с необходимыми свойствами (текст, отступы) и передаём его в метод setContentView().
Програмнное создание активности
В основном мы пользуемся XML-разметкой для формирования внешнего вида активности. Это рекомендованный способ и в 99% вы будете использовать именно его. Но в некоторых случаях возможно вам понадобится создать активность программно. Сложного там ничего нет, для общего развития пригодится.
Если в стандартном случае мы подключаем XML-файл в методе setContentView(R.layout.activity_main), то при программном создании данный метод нам не понадобится. Удаляем его и пишем код:
Принцип формирования следующий — создаем объект LinearLayout (или другой контейнер) и настраиваем необходимые свойства. Далее создаём необходимые дочерние элементы и также настраиваем их свойства. Не забываем подключить дочерний элемент к родительскому через метод addView().
В данном примере мы также присваиваем компонентам идентификаторы через метод setId(), хотя необходимости в этом не было. В примере эта возможность показана для демонстрации. Если вы используете идентификаторы, то в файле res/values/stings.xml добавьте строчки:
Обычно опытные программисты создают отдельный файл для идентификаторов, например, res/values/ids.xml.
Классы Activity в Android
Android SDK включает набор классов, наследованных от Activity. Они предназначены для упрощения работы с виджетами, которые часто встречаются в обычном пользовательском интерфейсе. Перечислим некоторые из них (наиболее полезные).
- MapActivity. Инкапсулирует обработку ресурсов, необходимых для поддержки элемента MapView внутри Активности.
- ListActivity. Обертка для класса Activity, главная особенность которой — виджет ListView, привязанный к источнику данных, и обработчики, срабатывающие при выборе элемента из списка.
- ExpandableListActivity. То же самое, что и ListActivity, но вместо ListView поддерживает ExpandableListView.
- TabActivity. Позволяет разместить несколько Активностей или Представлений в рамках одного экрана, используя вкладки для переключения между элементами.
Источник
Activity
Activity и жизненный цикл приложения
Ключевым компонентом для создания визуального интерфейса в приложении Android является activity (активность). Нередко activity ассоциируется с отдельным экраном или окном приложения, а переключение между окнами будет происходить как перемещение от одной activity к другой. Приложение может иметь одну или несколько activity. Например, при создании проекта с пустой Activity в проект по умолчанию добавляется один класс Activity — MainActivity, с которого и начинается работа приложения:
Все объекты activity представляют собой объекты класса android.app.Activity , которая содержит базовую функциональность для всех activity. В приложении из прошлой темы мы напрямую с этим классом не работали, а MainActivity наследовалась от класса AppCompatActivity . Однако сам класс AppCompatActivity, хоть и не напрямую, наследуется от базового класса Activity.
Жизненный цикл приложения
Все приложения Android имеют строго определенный системой жизненный цикл. При запуске пользователем приложения система дает этому приложению высокий приоритет. Каждое приложение запускается в виде отдельного процесса, что позволяет системе давать одним процессам более высокой приоритет, в отличие от других. Благодаря этому, например, при работе с одними приложениями Android позволяет не блокировать входящие звонки. После прекращения работы с приложением, система освобождает все связанные ресурсы и переводит приложение в разряд низкоприоритетного и закрывает его.
Все объекты activity, которые есть в приложении, управляются системой в виде стека activity, который называется back stack . При запуске новой activity она помещается поверх стека и выводится на экран устройства, пока не появится новая activity. Когда текущая activity заканчивает свою работу (например, пользователь уходит из приложения), то она удаляется из стека, и возобновляет работу та activity, которая ранее была второй в стеке.
После запуска activity проходит через ряд событий, которые обрабатываются системой и для обработки которых существует ряд обратных вызовов:
Схематично взаимосвязь между всеми этими обратными вызовами можно представить следующим образом
onCreate()
onCreate — первый метод, с которого начинается выполнение activity. В этом методе activity переходит в состояние Created. Этот метод обязательно должен быть определен в классе activity. В нем производится первоначальная настройка activity. В частности, создаются объекты визуального интерфейса. Этот метод получает объект Bundle , который содержит прежнее состояние activity, если оно было сохранено. Если activity заново создается, то данный объект имеет значение null. Если же activity уже ранее была создана, но находилась в приостановленном состоянии, то bundle содержит связанную с activity информацию.
После того, как метод onCreate() завершил выполнение, activity переходит в состояние Started , и и система вызывает метод onStart()
onStart
В методе onStart() осуществляется подготовка к выводу activity на экран устройства. Как правило, этот метод не требует переопределения, а всю работу производит встроенный код. После завершения работы метода activity отображается на экране, вызывается метод onResume , а activity переходит в состояние Resumed.
onResume
При вызове метода onResume activity переходит в состояние Resumed и отображается на экране устройства, и пользователь может с ней взаимодействовать. И собственно activity остается в этом состоянии, пока она не потеряет фокус, например, вследствии переключения на другую activity или просто из-за выключения экрана устройства.
onPause
Если пользователь решит перейти к другой activity, то система вызывает метод onPause , а activity переходит в состояние Paused . В этом методе можно освобождать используемые ресурсы, приостанавливать процессы, например, воспроизведение аудио, анимаций, останавливать работу камеры (если она используется) и т.д., чтобы они меньше сказывались на производительность системы.
Но надо учитывать, что в этот состоянии activity по прежнему остается видимой на экране, и на работу данного метода отводится очень мало времени, поэтому не стоит здесь сохранять какие-то данные, особенно если при этом требуется обращение к сети, например, отправка данных по интернету, или обращение к базе данных — подобные действия лучше выполнять в методе onStop() .
После выполнения этого метода activity становится невидимой, не отображается на экране, но она все еще активна. И если пользователь решит вернуться к этой activity, то система вызовет снова метод onResume , и activity снова появится на экране.
Другой вариант работы может возникнуть, если вдруг система видит, что для работы активных приложений необходимо больше памяти. И система может сама завершить полностью работу activity, которая невидима и находится в фоне. Либо пользователь может нажать на кнопку Back (Назад). В этом случае у activity вызывается метод onStop .
onStop
В этом методе activity переходит в состояние Stopped. В этом состоянии activity полностью невидима. В методе onStop следует особождать используемые ресурсы, которые не нужны пользователю, когда он не взаимодействует с activity. Здесь также можно сохранять данные, например, в базу данных.
При этом во время состояния Stopped activity остается в памяти устройства, сохраняется состояние всех элементов интерфейса. К примеру, если в текстовое поле EditText был введен какой-то текст, то после возобновления работы activity и перехода ее в состояние Resumed мы вновь увидим в текстовом поле ранее введенный текст.
Если после вызова метода onStop пользователь решит вернуться к прежней activity, тогда система вызовет метод onRestart . Если же activity вовсе завершила свою работу, например, из-за закрытия приложения, то вызывается метод onDestroy() .
onDestroy
Ну и завершается работа activity вызовом метода onDestroy , который возникает либо, если система решит убить activity в силу конфигурационных причин (например, поворот экрана или при многоконном режиме), либо при вызове метода finish() .
Также следует отметить, что при изменении ориентации экрана система завершает activity и затем создает ее заново, вызывая метод onCreate .
В целом переход между состояниями activity можно выразить следующей схемой:
Расмотрим несколько ситуаций. Если мы работаем с Activity и затем переключаемся на другое приложение, либо нажимаем на кнопку Home, то у Activity вызывается следующая цепочка методов: onPause -> onStop . Activity оказывается в состоянии Stopped. Если пользователь решит вернуться к Activity, то вызывается следующая цепочка методов: onRestart -> onStart -> onResume .
Другая ситуация, если пользователь нажимает на кнопку Back (Назад), то вызывается следующая цепочка onPause -> onStop -> onDestroy . В результате Activity уничтожается. Если мы вдруг захотим вернуться к Activity через диспетчер задач или заново открыв приложение, то activity будет заново пересоздаваться через методы onCreate -> onStart -> onResume
Управление жизненным циклом
Мы можем управлять этими событиями жизненного цикла, переопределив соответствующие методы. Для этого возьмем из прошлой главы класс MainActivity и изменим его следующим образом:
Для логгирования событий здесь используется класс android.util.Log .
В данном случае обрабатываются все ключевые методы жизненного цикла. Вся обработка сведена к вызову метода Log.d() , в который передается TAG — случайное строковое значение и строка, которая выводится в консоли Logcat в нижней части Android Studio, выполняя роль отладочной информации. Если эта консоль по умолчанию скрыта, то мы можем перейти к ней через пункт меню View -> Tool Windows -> Logcat .
И при запуске приложения мы сможем увидеть в окне Logcat отладочную информацию, которая определяется в методах жизненного цикла activity:
Источник
Understanding the Android Application Class
The Application class in Android is the base class within an Android app that contains all other components such as activities and services. The Application class, or any subclass of the Application class, is instantiated before any other class when the process for your application/package is created.
This class is primarily used for initialization of global state before the first Activity is displayed. Note that custom Application objects should be used carefully and are often not needed at all.
In many apps, there’s no need to work with an application class directly. However, there are a few acceptable uses of a custom application class:
- Specialized tasks that need to run before the creation of your first activity
- Global initialization that needs to be shared across all components (crash reporting, persistence)
- Static methods for easy access to static immutable data such as a shared network client object
Note that you should never store mutable shared data inside the Application object since that data might disappear or become invalid at any time. Instead, store any mutable shared data using persistence strategies such as files, SharedPreferences or SQLite .
If we do want a custom application class, we start by creating a new class which extends android.app.Application as follows:
And specify the android:name property in the the node in AndroidManifest.xml :
That’s all you should need to get started with your custom application.
There is always data and information that is needed in many places within your app. This might be a session token, the result of an expensive computation, etc. It might be tempting to use the application instance in order to avoid the overhead of passing objects between activities or keeping those in persistent storage.
However, you should never store mutable instance data inside the Application object because if you assume that your data will stay there, your application will inevitably crash at some point with a NullPointerException . The application object is not guaranteed to stay in memory forever, it will get killed. Contrary to popular belief, the app won’t be restarted from scratch. Android will create a new Application object and start the activity where the user was before to give the illusion that the application was never killed in the first place.
So how should we store shared application data? We should store shared data in one of the following ways:
- Explicitly pass the data to the Activity through the intent.
- Use one of the many ways to persist the data to disk.
Bottom Line: Storing data in the Application object is error-prone and can crash your app. Prefer storing your global data on disk if it is really needed later or explicitly pass to your activity in the intent’s extras.
Источник