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 Tasks Stack. Почитать об этом можно в документации или в Уроке 116.
Для примера возьмем почтовое приложение, состоящее из трех экранов: список писем (MainActivity), содержимое письма (DetailsActivity) и информация о новой версии (WhatsNewActivity). При запуске приложения MainActivity отображает письма, а по нажатию на письмо открывается DetailsActivity c содержимым письма.
У приложения есть какой-то сервис, который связан с сервером. Когда на сервере появляется новое письмо, сервис скачивает его и показывает пользователю уведомление. Пользователь нажимает на него и открывается DetailsActivity для просмотра письма.
Аналогично, сервис получает информацию о новой версии приложения и создает уведомление для этого события. По нажатию на уведомление будет открываться WhatsNewActivity, в котором будут подробно расписаны новые фичи приложения.
Но открывать два этих Activity мы будем разными способами.
DetailsActivity мы будем открывать так же, как если бы оно было открыто из MainActivity. Т.е. мы откроем сразу два Activity (одно за другим): MainActivity и DetailsActivity. Нажав Назад в открывшемся DetailsActivity пользователь попадет в MainActivity.
С экраном WhatsNewActivity ситуация другая. Он предназначен только для открытия из уведомления. Из приложения его открыть невозможно. Т.е. в приложении просто нет такого списка или такой кнопки, которые открыли бы WhatsNewActivity. Потому что это не особо важная информация, и, если вы вдруг сами захотели посмотреть ее, вы можете сходить на сайт приложения.
Давайте рассмотрим, как реализуются два этих варианта
DetailsActivity, как часть приложения
Сначала настроим DetailsActivity в манифесте:
Атрибут parentActivityName и тег meta-data здесь делают абсолютно одно и тоже — они сообщают, что DetailsActivity открывается из MainActivity. Т.е. MainActivity является родительским для DetailsActivity. Различие лишь в том, что meta-data работает для Android 4.0.3 и ниже, а parentActivityName — для Android 4.1 и выше. Т.е. указываем параметр parentActivity двумя разными способами для обеспечения совместимости. Если ваше приложение уже не поддерживает Android ниже 4.1, то meta-data вы можете не указывать.
Далее создаем уведомление. Все так же, как мы рассматривали в прошлом уроке. Отличаться будет только создание PendingIntent.
EXTRA_ITEM_ID — это ваша строковая константа
Рассмотрим по шагам, что здесь происходит.
Создаем обычный Intent для открытия DetailsActivity. Передаем туда id, чтобы Activity знало, какую информацию ему надо отобразить. Тут все понятно и обычно.
Затем создаем TaskStackBuilder — инструмент, который поможет нам сформировать последовательность вызовов Activity. Нам надо, чтобы сначала запустилось родительское Activity для DetailsActivity (т.е. MainActivity), а затем и само DetailsActivity.
Вызываем метод )» target=»_blank» rel=»noopener noreferrer»>addParentStack и указываем в нем DetailsActivity, т.е. просим в стек вызовов добавить Activity, которое является родительским для DetailsActivity. TaskStackBuilder идет в манифест и видит, что для DetailsActivity в качестве родительского (parentActivityName) прописано MainActivity. TaskStackBuilder добавляет MainActivity в стек вызовов.
В addNextIntent мы просто передаем Intent для запуска DetailsActivity. TaskStackBuilder добавит его в свой стек вызовов.
В итоге TaskStackBuilder содержит в стеке вызовов два Activity: сначала MainActivity, а затем DetailsActivity.
Методом getPendingIntent он формирует PendingIntent, который мы сможем передать в билдер уведомления. И по нажатию на уведомление будут открыты Activity, которые были в стеке вызовов, сформированном в TaskStackBuilder.
Запускаем, жмем на уведомление
И открываются два Activity. Нажав Назад в DetailsActivity мы попадаем в MainActivity.
Все работает, но осталась одна мелочь. Уведомление не закрывается по нажатию на него. Можно использовать setAutoCancel, как мы делали в прошлом уроке, но это не совсем правильно в данном случае.
Допустим вам приходит уведомление о новом письме. Но вы пока не открывали это уведомление, а решили сразу зайти в приложение, там уже увидели новое письмо, открыли его, прочитали и закрыли приложение. Письмо теперь прочитано вами, а уведомление продолжает висеть, хотя оно уже не актуально.
Правильнее будет удалять уведомление при открытии соответствующего ему письма. Рассмотрим, как это можно реализовать.
Код создания уведомления:
Весь код нам уже знаком. Пройдусь только по части id.
У вас есть id письма (itemId), пусть он будет long. Используя itemId, вы можете создать id для уведомления (notificationId) и далее указать его в методе notify.
Теперь, чтобы удалить уведомление, вам необходимо использовать такой же notificationId в методе cancel.
Реализуем это в DetailsActivity:
Достаем itemId из Intent. Из itemId снова формируем notificationId и используем его в методе cancel.
В результате, при открытии письма в DetailsActivity, уведомление, соответствующее этому письму, будет удалено. И неважно, пришли вы на этот экран сами или по нажатию на уведомление.
Важно, чтобы notificationId, используемый при показе и удалении уведомления совпадал. В нашем примере мы вычисляем его из itemId, просто взяв int часть от long. У вас может быть другой способ получения или формирования этого id.
WhatsNewActivity, отдельное от приложения
Рассмотрим другой вариант. Напомню, что он предполагает открытие Activity отдельно от приложения.
Для этого Activity должно быть настроено следующим образом в манифесте:
launchMode установлен в singleTask, чтобы Activity искало или создавало свой таск. taskAffinity делаем пустым, чтобы Activity не ушло в основной таск приложения. excludeFromRecents нужен, чтобы таск этого Activity не отображался в recent списке приложений.
Создание уведомления выполняется по обычной схеме, только в Intent надо добавить пару флагов, чтобы Activity стартовало в новом пустом таске
В итоге, по нажатию на уведомление будет открываться Activity в отдельном от вашего приложения таске.
И его не будет видно в списке последних запущенных приложений
Присоединяйтесь к нам в Telegram:
— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование
— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме
Источник
Полный список
В этом уроке мы:
— создадим и вызовем второе Activity в приложении
Урок был обновлен 12.06.2017
Мы подобрались к очень интересной теме. На всех предыдущих уроках мы создавали приложения, которые содержали только один экран (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
Присоединяйтесь к нам в Telegram:
— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование
— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме
Источник