В какой файл обязательно добавляется информация при создании нового activity в приложении
Класс Activity является важным компонентом приложения для Android, а способ запуска и объединения Activity является фундаментальной частью модели приложения платформы. В отличие от парадигм программирования, в которых приложения запускаются с помощью метода main (), система Android инициирует код в экземпляре Activity, вызывая определенные методы обратного вызова, которые соответствуют определенным этапам его жизненного цикла.
Мобильное приложение отличается от своего настольного аналога тем, что взаимодействие пользователя с приложением не всегда начинается с одного и того же места. Вместо этого путешествие пользователя часто начинается недетерминированно. Например, если вы откроете почтовое приложение на главном экране, вы можете увидеть список писем. Напротив, если вы используете приложение для социальных сетей, которое затем запускает ваше почтовое приложение, вы можете перейти непосредственно к экрану почтового приложения для составления электронного письма.
Класс Activity разработан для облегчения этой парадигмы. Когда одно приложение вызывает другое, вызывающее приложение вызывает Activity в другом приложении, а не в приложении как атомарном целом. Таким образом, Activity служит точкой входа для взаимодействия приложения с пользователем. Вы реализуете действие как подкласс класса Activity.
Activity предоставляет окно, в котором приложение рисует свой пользовательский интерфейс. Это окно обычно заполняет экран, но может быть меньше экрана и располагаться поверх других окон. Как правило, одно Activity реализует один экран в приложении. Например, одно из Activity приложения может реализовывать экран настроек, а другое Activity реализует экран выбора фотографии.
Большинство приложений содержат несколько экранов, что означает, что они включают несколько Activity. Как правило, одно Activity в приложении указывается как основное Activity, которое является первым экраном, который появляется, когда пользователь запускает приложение. Затем каждое Activity может запускать другое Activity для выполнения различных действий. Например, основным Activity в простом приложении электронной почты может быть экран, на котором отображается почтовый ящик. Отсюда основное Activity может запускать другие Activity, которые предоставляют экраны для таких задач, как написание электронных писем и открытие отдельных электронных писем.
Чтобы использовать Activity в своем приложении, вы должны зарегистрировать информацию о них в манифесте приложения и соответствующим образом управлять жизненными циклами Activity.
Мы подобрались к очень интересной теме. На всех предыдущих уроках мы создавали приложения, которые содержали только один экран (Activity). Но если вы пользуетесь смартфоном с Android, то вы замечали, что экранов в приложении обычно больше. Если рассмотреть, например, почтовое приложение, то в нем есть следующие экраны: список аккаунтов, список писем, просмотр письма, создание письма, настройки и т.д. Пришла и нам пора научиться создавать многоэкранные приложения.
Application/Library name: TwoActivity
Module name: p0211twoactivity
Package name: ru.startandroid.p0211twoactivity
Откроем activity_main.xml и создадим такой экран:
На экране одна кнопка, по нажатию которой будем вызывать второй экран.
Открываем MainActivity.java и пишем код:
Мы определили кнопку btnActTwo и присвоили ей Activity в качестве обработчика. Реализация метода onClick для кнопки пока заполнена частично - определяем, какая кнопка была нажата. Чуть позже здесь мы будем вызывать второй экран. Но сначала этот второй экран надо создать.
Если помните, при создании проекта у нас по умолчанию создается Activity.
От нас требуется только указать имя этого Activity – обычно мы пишем здесь MainActivity. Давайте разбираться, что при этом происходит.
Мы уже знаем, что создается одноименный класс MainActivity.java – который отвечает за поведение Activity. Но, кроме этого, Activity «регистрируется» в системе с помощью манифест-файла - AndroidManifest.xml.
Давайте откроем этот файл:
Нас интересует тег application. В нем мы видим тег activity с атрибутом name = MainActivity. В activity находится тег intent-filter с определенными параметрами. Пока мы не знаем что это и зачем, сейчас нам это не нужно. Забегая вперед, скажу, что android.intent.action.MAIN показывает системе, что Activity является основной и будет первой отображаться при запуске приложения. А android.intent.category.LAUNCHER означает, что приложение будет отображено в общем списке приложений Android.
Т.е. этот манифест-файл - это что-то типа конфигурации. В нем мы можем указать различные параметры отображения и запуска Activity или целого приложения. Если в этом файле не будет информации об Activity, которое вы хотите запустить в приложении, то вы получите ошибку.
Android Studio при создании модуля создала MainActivity и поместила в манифест данные о нем. Если мы надумаем сами создать новое Activity, то студия также предоставит нам визард, который автоматически добавит создаваемое Activity в манифест.
Давайте создадим новое Activity
Жмем правой кнопкой на package ru.startandroid.p0211twoactivity в папке проекта и выбираем New -> Activity -> Empty Activity
В появившемся окне вводим имя класса – ActivityTwo, и layout – activity_two.
Класс ActivityTwo создан.
В setContentView сразу указан layout-файл activty_two.
Он был создан визардом
Откройте activty_two.xml и заполните следующим кодом:
Экран будет отображать TextView с текстом "This is Activity Two".
Сохраните все. Класс ActivityTwo готов, при отображении он выведет на экран то, что мы настроили в layout-файле two.xml.
Давайте снова заглянем в файл манифеста
Появился тег activity с атрибутом name = .ActivityTwo. Этот тег совершенно пустой, без каких либо параметров и настроек. Но даже пустой, он необходим здесь.
Нам осталось вернуться в MainActivity.java и довершить реализацию метода onClick (нажатие кнопки), а именно - прописать вызов ActivityTwo. Открываем MainActivity.java и добавляем строки:
(добавляете только строки 2 и 3)
Обновите импорт, сохраните все и можем всю эту конструкцию запускать. При запуске появляется MainActivity
Нажимаем на кнопку и переходим на ActivityTwo
Код вызова Activity пока не объясняю и теорией не гружу, урок и так получился сложным. Получилось много текста и скриншотов, но на самом деле процедура минутная. Поначалу, возможно, будет непонятно, но постепенно втянемся. Создадим штук 5-6 новых Activity в разных проектах и тема уляжется в голове.
Пока попробуйте несколько раз пройти мысленно эту цепочку действий и усвоить, что для создания Activity необходимо создать класс (который наследует android.app.Activity) и создать соответствующую запись в манифест-файле.
На следующем уроке:
- разбираемся в коде урока 21
- теория по Intent и Intent Filter (не пропустите, тема очень важная)
- немного о Context
- в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование
- ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
- новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме
Activity - это компонент приложения, который является одним из его фундаментальных строительных блоков. Его основное предназначение заключается в том, что оно служит точкой входа для взаимодействия приложения с пользователем, а также отвечает за то, как пользователь перемещается внутри приложения или между приложениями.
По сути активити - это окно, с которым пользователь взаимодействует. И в этом окне можно “нарисовать” какой-либо пользовательский интерфейс. При этом окно может быть как на весь экран, так и занимать только заданную его часть и даже размещаться поверх других окон. Но, как правило, каждая активити реализует только одно окно. Однако, у каждого приложения может быть несколько активити.
Одна из активити может быть отмечена как основная (или главная) и тогда она будет появляться первой при запуске приложения. А уже из нее можно запустить другие активити. Причем не только те, которые принадлежат текущему приложению, но и активити из других приложений. Может показаться, что все запускаемые активити являются частями одного приложения. На самом же деле они могут быть определены в разных приложениях и работать в разных процессах.
Мне встречалась интересная аналогия, что активити - это как страницы разных сайтов, открываемых в браузере по ссылке.
Создание новой активити
Первым делом следует создать новый класс, который должен наследоваться от класса Activity и переопределять метод onCreate() .
Таким образом мы получим пустое окно. Чтобы в этом окне хоть что-то отображалось нужно создать разметку - layout. Добавляется она в ресурсах (папка res) в подпапке layout.
Теперь эту разметку нужно “подключить” к активити в методе onCreate() .
Ну и наконец, чтобы приложение могло использовать только что созданную активити её нужно объявить в манифесте приложения при помощи элемента <activity> .
Все вышеперечисленные шаги можно сократить до одного благодаря наличию в Android Studio стандартных шаблонов: правой кнопкой мыши вызываем контекстное меню и в нём выбираем New -> Activity -> “выбрать нужный шаблон”.
После этого класс, разметка, а также запись в манифесте будут добавлены автоматически.
Настройка активити в манифесте
Рассмотрим более подробно, какую информацию нужно или можно добавлять для элемента <activity> в манифесте.
Объявление активити
Как упоминалось выше, все активити приложения обязательно нужно регистрировать в манифесте. Для этого предназначен элемент <activity> . У этого элемента есть только один обязательный атрибут - android:name , который ссылается на имя класса активити.
При этом, если приложение уже опубликовано, то не следует менять имя класса, так как это может привести к негативным последствиям. Для часто используемого приложения пользователь, как правило, создает ярлык на главном экране устройства. Ярлык представляет из себя Intent , который, используя имя класса, указывает какой компонент должен быть запущен. Поэтому при смене имени класса сломаются все ярлыки, а пользователь будет недоволен.
Помимо обязательного атрибута существуют и другие, с помощью которых каждой активити можно задать уникальные заголовок, иконку, тему и многие другие характеристики. Подробнее с ними можно ознакомиться в моей статье про манифест или в официальной документации.
Объявление intent-фильтров
Скорее всего данная тема будет не особо понятна новичкам, поэтому сначала рекомендую ознакомиться с тем, что такое Intent.
Intent-фильтры - это выражение в файле манифеста, которое указывает, какие объекты Intent может обработать текущее приложение. Т.е. они позволяют настроить, на что будет реагировать активити.
Если у приложения отсутствуют intent-фильтры, то запустить его можно будет только с помощью явного Intent (по имени класса).
Объявляются они при помощи атрибута <intent-filter> внутри элемента <activity> . При этом <intent-filter> должен обязательно содержать атрибут <action> и может содержать необязательные атрибуты <category> и <data> . Все вместе эти элементы указывают на тип объекта Intent , на который текущая активити сможет реагировать.
Например, активити можно добавить intent-фильтр, который будет говорить, что она умеет отправлять данные.
Выше упоминалось, что активити можно отметить как основную. Это тоже осуществляется с помощью intent-фильтра.
Объявление разрешений
С помощью разрешений можно контролировать, какие приложения могут запускать активити. При этом одна активити не сможет запустить другую, если они не имеют одинаковых разрешений в манифесте.
Например, ваше приложение хочет использовать приложение SocialApp для публикации какой-либо информации в социальных сетях. Приложение SocialApp должно определить разрешение:
И чтобы иметь возможность запускать SocialApp вы должны в своем приложении добавить идентичное разрешение:
Жизненный цикл
При использовании приложения мы постоянно перемещаемся от одного экрана к другому и обратно. Поэтому все активити, с которыми мы взаимодействуем постоянно меняют состояние своего жизненного цикла. А чтобы узнать о смене состояния существуют методы обратного вызова. Т.е. как только активити перешла в другое состояние, сразу же вызывается соответствующий метод обратного вызова. Таким образом можно отслеживать смену состояния и реагировать на него.
Для чего это делать? Чтобы избежать следующих ситуаций:
- Сбой приложения, когда пользователю поступает звонок или когда он переключается на другое приложение.
- Потребление ценных ресурсов, даже если пользователь активно не пользуется приложением в данный момент.
- Потеря прогресса пользователя, если он переключился на другое приложение или временно из него вышел.
- Сбой или потеря прогресса при смене ориентации экрана с портретной на альбомную и обратно.
Это вовсе не означает, что каждый раз нужно реализовывать все методы обратного вызова. Требуется лишь понять для чего каждый из них предназначен, чтобы использовать их в нужный момент.
Методы обратного вызова
onCreate()
Вызывается при создании и перезапуске активити. После создания активити она переходит в состояние “Создана” (Created state), но существует в нём недолго. Как только метод onCreate() будет выполнен, активити переходит в статус “Запущена” (Started state).
Этому методу передается объект Bundle , который содержит в себе сохранённое состояние активити (если она перезапустилась), либо null (если активити ранее не существовала).
Что в нём должно происходить:
Выполнение базовой логики запуска приложения, которая должна происходить только один раз за весь период действия. Например, создание пользовательского интерфейса, привязка данных, создание сервисов (service) и потоков.
Следующий метод:
onStart() .
onStart()
Вызывается при переходе активити в состояние “Запущена” (Started state), т.е. сразу после выполнения метода onCreate() . В этом состоянии активити существует пока метод onStart() не будет выполнен. После чего переходит в состояние “Возобновлена” (Resumed state).
Также этот метод делает активити видимой для пользователя, но с ней еще нельзя взаимодействовать.
Что в нём должно происходить:
Выполнение кода, который поддерживает пользовательский интерфейс
Следующий метод:
onResume()
onResume()
Вызывается при переходе активити в состояние “Возобновлена” (Resumed state), т.е. сразу после выполнения метода onStart() . В этом состоянии активити взаимодействует с пользователем. И продолжается это до тех пор пока пользователя что-то не отвлечёт, например, телефонный звонок, переход к другому приложению или отключение экрана устройства. В этом случае активити перейдёт в состояние “Приостановлена” (Paused state).
Что в нём должно происходить:
Включение функциональности, которая должна работать, пока активити видна и находится на переднем плане. Возобновить работу того, что было приостановлено в методе onPause() .
Следующий метод:
onPause()
onPause()
Вызывается, когда активити теряет фокус и переходит в состояние “Приостановлена” (Paused state). Т.е. активити больше не находится на переднем плане, хотя может быть всё ещё видна пользователю.
Завершение работы метода onPause() не означает, что активити перейдёт в другое состояние. Она будет оставаться в состоянии “Приостановлена” до тех пор, пока либо не перейдёт обратно на передний план (вызовется метод onResume() ), либо пока полностью не станет невидимой (вызовется метод onStop() ).
Что в нём должно происходить:
Приостановка или настройка операций, которые не должны продолжаться пока активити находится в состоянии “Приостановлена”, но ожидается, что вы вскоре их возобновите.
Код должен быть легковесным, так как нет гарантии, что он успеет выполнится.
Следующий метод:
onResume() или onStop() .
onStop()
Вызывается, когда активити больше не видна пользователю и переходит в состояние “Остановлена”. Это может произойти, если активити уничтожается, запускается новая активити или возобновляет работу существующая активити, закрывая собой текущую. Несмотря на это, активити остаётся в памяти, но она больше не привязана к диспетчеру окон.
Из состояния “Остановлена” активити либо возвращается к взаимодействию с пользователем (вызывается метод onRestart() ), либо завершается (вызывается метод onDestroy() ).
Что в нём должно происходить:
Остановка функций, работа которых не нужна пока активити невидима для пользователя. Например, остановка анимаций, сохранение информации в базе данных.
Следующий метод:
onRestart() или onDestroy() .
onRestart()
Вызывается, когда активити в состоянии “Остановлена” повторно отображается пользователю.
Что в нём должно происходить:
Выполнение действий, которые должны выполняться при повторном запуске активити в рамках одного жизненного цикла приложения.
Следующий метод:
onStart() .
onDestroy()
Вызывается перед тем, как активити будет уничтожена и переходит в состояние “Уничтожена” (Destroyed state). Это происходит в следующих случаях: если пользователь её закрыл; был вызван метод finish() ; произошла смена конфигурации активити (например, поворот экрана). При этом в первых двух случаях метод onDestroy() будет последним обратным вызовом в жизненном цикле активити. Если же onDestroy() был вызван из-за смены конфигурации, система немедленно создаст новый экземпляр активити и вызовет для него метод onCreate() .
Что в нём должно происходить:
Освобождение всех оставшихся ресурсов, которые не были освобождены в методах onPause() и onStop() .
Не использовать для какой-либо критически важной логики, так как данный метод может быть и не вызван.
Следующий метод:
Последний метод жизненного цикла.
Схема состояний активити
Исходя из вышеописанного можно сделать простенькую схему для лучшего понимания того, как активити переходит из одного состояния своего жизненного цикла в другое. Я делаю акцент именно на состояниях (а не на методах обратного вызова), потому что на мой взгляд это легче для восприятия (особенно новичкам).
Android спроектирован так, чтобы использование приложения пользователем было максимально интуитивным. Например, пользователи приложения могут повернуть экран, ответить на уведомление или переключиться на другое приложение, и после этих манипуляций они все так же должны иметь возможность продолжить использовать приложение без каких-либо проблем.
Чтобы обеспечить такое взаимодействие с пользователем, вы должны знать, как управлять жизненными циклами компонентов. Компонентом может быть Activity, Fragment, Service, класс Application и даже сам процесс приложения. Компонент имеет жизненный цикл, в течение которого он проходит через различные состояния. Всякий раз, когда происходит переход, система уведомляет вас об этом при помощи методов жизненного цикла.
Чтобы нам было легче объяснить, как работает жизненный цикл в Android, мы определили несколько сценариев (примеров из жизни), которые сгруппированы по компонентам:
Часть 1: Activity — ЖЦ одного активити (этот пост)
Диаграммы также доступны в виде шпаргалки в формате PDF для краткого ознакомления.
Примечание: эти диаграммы соответствуют поведению в Android P/Jetpack 1.0.
Следующие сценарии демонстрируют поведение компонентов по умолчанию, если не указано иное.
Если вы обнаружили ошибки в статье или считаете, что не хватает чего-то важного, напишите об этом в комментариях.
Часть 1: Activity
Одно Aсtivity - Сценарий 1. Приложение завершено и перезапущено
Будет вызван, если:
Вызван метод Activity.finish()
Самый простой сценарий показывает, что происходит, когда приложение с одним активити запускается, завершается и перезапускается пользователем:
Управление состоянием
onSaveInstanceState не вызывается (поскольку активити завершено, вам не нужно сохранять состояние)
onCreate не имеет Bundle при повторном открытии приложения, потому что активити было завершено и состояние не нужно восстанавливать.
Одно Aсtivity - Сценарий 2. Пользователь уходит
Будет вызван, если:
Пользователь нажимает кнопку "Домой"
Пользователь переключается на другое приложение (через меню «Все приложения», из уведомления, при принятии звонка и т. д.)
В этом случае система остановит активити, но не завершит его сразу.
Управление состоянием
Когда ваше активити переходит в состояние Stopped, система использует onSaveInstanceState для сохранения состояния приложения на тот случай, если впоследствии система завершит процесс приложения (см. ниже).
Предполагая, что процесс не был убит, экземпляр активити сохраняется в памяти, сохраняя все состояние. Когда активити возвращается на передний план, вам не нужно повторно инициализировать компоненты, которые были созданы ранее.
Одно Aсtivity - Сценарий 3. Изменение кофигурации
Будет вызван, если:
Изменена конфигурация, такие как поворот экрана
Пользователь изменил размер окна в многооконном режиме
Управление состоянием
Изменения конфигурации, такие как поворот или изменение размера окна, должны позволить пользователям продолжить работу с того места, где они остановились.
Активити полностью уничтожено, но состояние сохраняется и восстанавливается при создании нового экземпляра.
Bundle в onCreate тот же самый, что и в onRestoreInstanceState .
Одно Aсtivity - Сценарий 4. Приложение приостановлено системой
Будет вызван, если:
Включён многооконный режим (API 24+) и потерян фокус
Другое приложение частично покрывает работающее приложение: диалоговое окно покупки (in-app purchases), диалоговое окно получения разрешения (Runtime Permission), стороннее диалоговое авторизации и т. д.
Появится окно выбора приложения (при обработке неявного интента), например диалоговое окно шейринга.
Этот сценарий не применим к:
Диалогам в том же приложении. Отображение AlertDialog или DialogFragment не приостанавливает базовое активити.
Уведомлениям. Пользователь, получающий новое уведомление или открывающий панель уведомлений, не приостанавливает текущее активити.
Читайте также:
- Как зарегистрироваться в приложении госуслуги культура
- Подпись мобильного клиента в приложении на сервере устарела необходимо обновить подпись как убрать
- Приложение v live на русском как сделать
- Почему не открывается ссылка на яндекс диск на телефоне
- Девушка отослала фото отцу в вайбере с подписью гуляем у озера с максимом не теряй