Android java single activity

Что такое Activity и его жизненный цикл в Android

Russian (Pусский) translation by Ellen Nelson (you can also view the original English article)

Из моей предыдущей статьи вы узнали, что Intents позволяют отправлять сообщения с одного компонента Android на другой. А очень важным компонентом является Activity.

Activities являются основной частью разработки приложений для Android. И невозможно понять Activity, не понимая их жизненных циклов. В этом материале вы узнаете всё о жизненном цикле Activity.

Жизненный цикл Activity

Activity — это отдельный экран в Android. Это как окно в приложении для рабочего стола, или фрейм в программе на Java. Activity позволяет вам разместить все ваши компоненты пользовательского интерфейса или виджеты на этом экране.

Важно понимать, что у Activity есть жизненный цикл, проще говоря, это означает, что она может быть в одном из различных стадий, в зависимости от того, что происходит с приложением при действиях пользователя.

Методы жизненного цикла

Давайте поближе рассмотрим жизненный цикл Android Activity. Каждый раз, когда Activity меняет стадию, вызывается один из следующих методов жизненного цикла для класса Activity.

onCreate() : вызывается при первой инициализации Activity. Вам нужно выполнить этот метод для выполнения любой инициализации в вашей Activity.

onStart() : это вызывается, когда Activity готова и отображается пользователю в первый раз, так как Activity готовится стать интерактивной и выйти на передний план. После завершения вызова этого метода, будет вызван метод onResume() .

onResume() : когда Activity переходит в это состояние, оно начинает взаимодействовать с пользователем. Activity продолжает работать в этом состоянии, пока что-либо не уведёт фокус от приложения или Activity (например, входящий звонок). Если это произойдет, будет вызван метод onPause() .

onPause() : этот метод используется для приостановки действий, которые не должны происходить, пока Activity в стадии паузы. Вызов этого метода указывает на то, что пользователь покинул приложение. К примеру, входящий звонок может перевести, проигрыватель музыки в состояние паузы. Это должно заглушить или остановить воспроизводящуюся музыку. Когда пользователь возвращается в приложение, вызывается метод onResume() .

onStop() : этот метод вызывается, если Activity больше не видна в приложении. Такое может случится, если подгружена другая Activity и она занимает весь экран устройства. Когда вызывает этот метод, Activity сообщается перейти в состояние прекращения работы. В этом состоянии, система либо вызывает onRestart() для возврата взаимодействия с Activity, либо вызывает метод onDestroy() , чтобу убрать Activity.

onDestroy() : этот метод вызывается перед тем, как Activity будет завершена. Система вызывает этот метод, когда пользователь завершает Activity, или если система временно убирает процесс, содержащий Activity, для высвобождения места. С этом методом, обязательно освободите любые ресурсы, созданные вашей Activity, иначе ваше приложение будет иметь утечку памяти.

onRestart() : это вызывается, если Activity перезапускается, после того, как было остановлено.

Запуск Activity

Большинство пользовательских взаимодействий приводит к изменению действующей Activity. Поэтому приложение моно раз переключается между Activity за свой жизненный цикл.

Необходимо связывать Activity друг с другом, если требуется чтобы одна Activity запускала другую. Для запуска Activity используйте либо startActivity() , либо startActivityForResult() . В обоих случаях вы должны передать Intent.

Запуск Activity без ожидаемого результата

startActivity() используется, если недавно запущенная Activity не должна возвращать результат.

Следующий фрагмент кода показывает как начать другую Activity, используя этот метод:

Можно также выполнять действия по передачи данных от одной Activity к другой. В этом случае, ваша текущая Activity (вызывающая Activity) хочет передать данные целевой Activity. Вот когда полезны Intents. Чтобы узнать больше об использовании Intents для запуска Activity, смотрите мой предыдущий урок.

Запуск Activity на результат

startActivityForResult() используется для запуска другой Activity и ожидает получение данных в эту свежезапущенную Activity. Другими словами, используйте это если хотите получить результат от целевой Activity в вызывающую Activity, т.е. если целевая Activity собирает некую пользовательскую информацию в модальном диалоговом окне.

Вы получите результат от Activity в методе onActivityResult(int requestCode, int resultCode, Intent data) . Результат будет возвращен в качестве Intent.

Пример запуска Activity

Вот пример, который показывает как работает запуск Activity

Во-первых создайте MainActivity с вашим методом onCreate() , файл макета и кодом запроса.

В методе onCreate() вы создадите новый экземпляр намерения (intent) чтобы запустить вторую Activity.

Когда будете готовы к запуску Activity, скажем в ответ на нажатие кнопки, вы вызовете startActivityForResult() , которая передаст свеже-созданное намерение и код запроса.

В вашей MainActivity , вам всё же нужно обработать результат событий Activity. Это выполняется путём реализации метода onActivityResult() . Вот так вы и получите результат от другой Activity.

Вот как это должно выглядеть:

Теперь создайте вашу SecondActivity . Это должно быть похоже на код ниже.

Прерывание Activity

Перед завершением Activity, будут вызваны соответствующие методы жизненного цикла.

Метод onPause() должен остановить все «слушания» и обновления интерфейса. Метод onStop() должен сохранять данные приложения. И наконец, метод onDestroy() высвободит любые ресурсы, выделенные для Activity.

Когда пользователь переключается обратно на приложение, которое было прервано системным событием, вызывается метод onResume() . На основе сохраненных данных, могут перерегистрироваться «слушатели» и переключиться обновления интерфейса.

Стадия экземпляра Activity

Activity нужен способ сохранить полезное состояние и пользовательские данные, которые она получила. Эти данные могут быть получены от пользователя или созданы, пока Activity не отображалась на экране.

Например, изменение ориентации устройства могут вызвать крушение Activity и её повторное создание. В этом случае, нужно убедиться, что сохранены все состояния Activity, прежде чем она распадётся и снова перезапустится. В противном случае, любые данные, которые были у вашей Activity в это время будут полностью утеряны.

Читайте также:  Эквалайзер для андроид для bluetooth 4pda

Чтобы сохранить состояние Activity, можно переопределить метод onSaveInstanceState(). Этот метод передаёт объект Bundle , в качестве параметра. Пакет (bundle) может содержать строки, простые типы данных или объекты. В этом методе, просто добавьте любые данные о важном состоянии в пакет (bundle). Позже этот пакет вернется Activity, так что вы сможете восстановить состояние Activity.

Чтобы извлечь сохраненное состояние из пакета и восстановить его (состояние), примените метод onRestoreInstanceState() . Этот callback вызывается между методами жизненного цикла onStart() и onResume() .

Мы получше рассмотрим состояние экземпляра Activity в будущих статьях.

Заключение

После просмотра этого материла, вы хорошо поймете, как работает жизненный цикл Activity. И вы узнали, что есть два способа запуска Activity, а также получение указателей на то, как обрабатывается состояние экземпляра в жизненном цикле Activity.

Спасибо за чтение, и пока вы здесь, ознакомьтесь с некоторыми другими нашими материалами о кодировании приложений для Android.

Источник

Полный список

— меняем поведение Activity в Task

Когда я в Уроке 25 говорил про Task, то решил, что рановато будет рассказывать про возможности изменения поведения Activity. Да и в хелпе можно найти такие слова: «The way Android manages tasks and the back stack (…) works great for most applications and you shouldn’t have to worry about how your activities are associated with tasks or how they exist in the back stack». Т.е. дефолтное поведение вполне подходит для большинства случаев и нам не надо о нем задумываться. Но вполне может встретиться ситуация, когда надо будет на это поведение влиять. Поговорим о том, какими средствами можно это делать. За основу возьмем статью «Tasks and Back Stack» из хелпа.

Про механизм заполнения Task я не рассказываю, все есть в Уроке 25. Давайте только определимся с формулировками. Таск – это Task. Корень таска или корневое Activity таска – это первое Activity, помещенное в таск. Топ таска или верхнее Activity в таске – это последнее Activity, добавленное в таск.

Для показательных примеров по теме нам понадобятся два приложения.

Первое состоит из 4 Activity: A,B,C,D. Они последовательно будут вызывать друг друга: A -> B -> C -> D. И D будет вызывать само себя: D -> D.
Второе приложение – это только одно Activity, оно будет вызывать C из первого приложения.

Project name: P1161_MngTasks1
Build Target: Android 4.1
Application name: MngTasks1
Package name: ru.startandroid.develop.p1161mngtasks1
Create Activity: MainActivity

Добавим строки в strings.xml:

Две кнопки. Вызов Activity и вывод информации в лог.

В onCreate мы в заголовок помещаем название приложения и имя класса Activity, чтобы на экране видеть какое Activity какого приложения сейчас активно.

В onInfoClick используем ActivityManager. Метод getRunningTasks вернет нам список текущих работающих тасков. Последние активные таски будут в начале списка. На всякий случай будем получать первые 10. Среди них точно окажутся два наших. Далее мы получаем информацию о таске: кол-во Activity (numActivities), корневое Activity (baseActivity), верхнее Activity (topActivity). И отсеиваем свои таски по имени пакета корневого Activity.

Этот класс будет предком для 4-х следующих. Он содержит абстрактный метод onClick, который нам надо будет реализовать в наследниках. Этот метод будет вызываться по нажатию на кнопку Start.

Создаем 4 Activity.

Все Activity наследуют MainActivity. А, значит, будут выводить в заголовок инфу о себе, а по нажатию на кнопку Info – показывать в логе текущую инфу по таскам.

Ну а метод onClick – это вызов следующего Activity. ActivityD будет вызывать себя же.

Прописываем в манифесте новые Activity. ActivityA назначим стартовым вместо MainActivity. ActivityC содержит фильтр с action = mngtasks1_activity_c. MainActivity удаляем из манифеста.

И добавьте права на получение данных о тасках: android.permission.GET_TASKS.

Первое приложение готово. Создаем второе. Оно полностью аналогичное, только Activity будет одно.

Project name: P1162_MngTasks2
Build Target: Android 4.1
Application name: MngTasks2
Package name: ru.startandroid.develop.p1162mngtasks2
Create Activity: MainActivity

Добавим строки в strings.xml:

В onClick идет вызов ActivityC из первого приложения.

В манифесте не забудьте про android.permission.GET_TASKS.

Все сохраним и запустим первое приложение.

В заголовке видим имя приложения и Activity. Жмем Info и смотрим лог:

Count: 1
Root: ru.startandroid.develop.p1161mngtasks1/.ActivityA
Top: ru.startandroid.develop.p1161mngtasks1/.ActivityA

В таске первого приложения одно Activity, корневое — ActivityA, верхнее — ActivityA.

Давайте нажмем Start три раза, чтобы пройти B,C и оказаться в D

Root: ru.startandroid.develop.p1161mngtasks1/.ActivityA
Top: ru.startandroid.develop.p1161mngtasks1/.ActivityD

Теперь в таске 4 Activity, корневое — A, верхнее – D. Между ними B и C.

Запустим второе приложение.

Count: 1
Root: ru.startandroid.develop.p1162mngtasks2/.MainActivity
Top: ru.startandroid.develop.p1162mngtasks2/.MainActivity
——————
Count: 4
Root: ru.startandroid.develop.p1161mngtasks1/.ActivityA
Top: ru.startandroid.develop.p1161mngtasks1/.ActivityD

В таске второго приложения одно Activity, корневое — MainActivity, верхнее — MainActivity. Таск первого не менялся.

Нажмем два раза Start: откроется C, затем D.

Они оба легли в таск второго приложения. Жмем Info:

Count: 3
Root: ru.startandroid.develop.p1162mngtasks2/.MainActivity
Top: ru.startandroid.develop.p1161mngtasks1/.ActivityD
——————
Count: 4
Root: ru.startandroid.develop.p1161mngtasks1/.ActivityA
Top: ru.startandroid.develop.p1161mngtasks1/.ActivityD

В таске второго приложения 3 Activity, корневое — MainActivity, верхнее — D.

Таск первого приложения не поменялся. Экземпляры ActivityC и AtivityD созданы в двух разных тасках.

Это стандартное поведение Activity в тасках. Используя эти два приложения, мы сейчас будем тестировать нестандартное поведение.

Для удобства запуска создадим ярлыки приложений на рабочем столе.

Очистим таски. Для этого надо вызвать приложение из списка последних вызываемых или через ярлык и нажимать Назад, пока все его Activity не закроются. Проделаем это для наших обоих приложений. Это желательно проделывать перед каждым примером.

launchMode

Начнем с launchMode. Это атрибут Activity. Может принимать значения: standard, singleTop, singleTask, singleInstance.

standard

standard – это дефолтное поведение, тут все ясно, его мы только что посмотрели.

singleTop

Если мы вызываем Activity, и оно уже находится в топе текущего Task-а, то новый экземпляр этого Activity создан не будет. Мы попадем в старый и получим там вызов метода onNewIntent.

Читайте также:  Android зарегистрироваться как разработчик

Откроем первое приложение, нажмем три раза Start, чтобы оказаться в D. На этот момент содержимое таска: A-B-C-D.

Теперь в D снова нажмем Start. Открылся еще один экземпляр D. Жмем Info и смотрим лог:

Count: 5
Root: ru.startandroid.develop.p1161mngtasks1/.ActivityA
Top: ru.startandroid.develop.p1161mngtasks1/.ActivityD

В верх таска добавилось еще одно D. Т.е. содержимое таска сейчас таково: A-B-C-D-D. ActivityD продублировалось. И если мы продолжим жать Start, так и будут создаваться новые экземпляры D. Открываем манифест и меняем у D свойство launchMode на singleTop.

Сохраняем, запускаем первое приложение. Жмем три раза Start, попадаем в D. Жмем еще раз Start, сразу визуально видно, что новое Activity не открывалось. Жмем Info и смотрим лог:

Count: 4
Root: ru.startandroid.develop.p1161mngtasks1/.ActivityA
Top: ru.startandroid.develop.p1161mngtasks1/.ActivityD

Система определяет, что наверху таска уже расположено ActivityD, которое мы хотим открыть, и оставляет нам его вместо создания новых экземпляров. Все последующие нажатия Start будут давать тот же результат. Т.к. новое ActivityD не создается, то и его метод onCreate не вызывается. В этом случае будет вызываться метод onNewIntent.

Прервемся на теорию, надо прояснить один момент. Activity имеет атрибут affinity. По умолчанию он равен пакету (package) приложения. У таска тоже есть атрибут affinity и при создании таска в этот атрибут помещается значение из affinity корневого Activity.

Т.е. когда мы запускаем первое приложение, то у созданного под него таска affinity = ru.startandroid.develop.p1161mngtasks1. Когда запускаем второе, новый созданный таск имеет affinity = ru.startandroid.develop.p1162mngtasks2.

Таким образом, для Activity можно принять такое понятие, как «свой» таск — когда affinity таска и Activity совпадают. Дальше в уроке мы еще поработаем с этим атрибутом. А пока нам надо просто понимать что такое «свой» таск.

singleTask

Вместо создания в текущем таске экземпляра вызываемого Activity будет выполнен поиск по другим таскам, и если будет найден «свой» таск, то Activity будет создано именно в нем. Если оно уже существует в своем таске, то оно и отобразится, а все Activity выше его в таске будут закрыты. Если же свой таск не найдется, то он будет создан и Activity станет там корневым. Посмотрим на примерах.

Проверим, как поведет себя ActivityC при вызове из второго приложения, если оно уже открыто в первом.

Давайте для ActivityC поменяем в манифесте свойство launchMode на singleTask. Сохраняем, запускаем первое приложение.

Жмем Start, пока не окажемся в D. Жмем Info и смотрим лог:

Count: 4
Root: ru.startandroid.develop.p1161mngtasks1/.ActivityA
Top: ru.startandroid.develop.p1161mngtasks1/.ActivityD

Все как обычно, С было создано в своем таске.

Теперь используем второе приложение. Напомню, что там из MainActivity как раз идет вызов ActivityC первого приложения. Как мы видели в начале урока, при стандартном поведении ActivityC просто добавляется в таск второго приложения. Посмотрим, что получится сейчас. Сворачиваем (кнопка Домой) первое приложение, запускаем второе.

Жмем Info и смотрим лог:

Root: ru.startandroid.develop.p1162mngtasks2/.MainActivity
Top: ru.startandroid.develop.p1162mngtasks2/.MainActivity
——————
Count: 4
Root: ru.startandroid.develop.p1161mngtasks1/.ActivityA
Top: ru.startandroid.develop.p1161mngtasks1/.ActivityD

В таске второго приложения только MainActivity. В таске первого A-B-C-D.

Жмем Start во втором приложении, открывается ActivityC:

Жмем Info и смотрим лог:

Root: ru.startandroid.develop.p1161mngtasks1/.ActivityA
Top: ru.startandroid.develop.p1161mngtasks1/.ActivityC
——————
Count: 1
Root: ru.startandroid.develop.p1162mngtasks2/.MainActivity
Top: ru.startandroid.develop.p1162mngtasks2/.MainActivity

Поведение значительно отличается от стандартного. Вместо того, чтобы создать экземпляр ActivityC в таске второго приложения, система нашла его в его родном таске первого приложения, и открыла, при этом закрыв все Activity, находящиеся выше его в таске (ActivityD в нашем случае).

Очистим таски кнопкой Назад.

Посмотрим, что будет, если ActivityC пока не запущено в своем таске. Запускаем первое приложение, ничего не жмем в нем, остаемся в ActivityA. Сворачиваем первое, запускаем второе приложение и жмем Start. Жмем Info, смотрим лог:

Root: ru.startandroid.develop.p1161mngtasks1/.ActivityA
Top: ru.startandroid.develop.p1161mngtasks1/.ActivityC
——————
Count: 1
Root: ru.startandroid.develop.p1162mngtasks2/.MainActivity
Top: ru.startandroid.develop.p1162mngtasks2/.MainActivity

ActivityC нашло свой таск и создалось в нем.

А что будет, если свой таск пока не создан? Очищаем таски кнопкой Назад. Запускаем второе приложение, жмем Info:

Count: 1
Root: ru.startandroid.develop.p1162mngtasks2/.MainActivity
Top: ru.startandroid.develop.p1162mngtasks2/.MainActivity

Таска первого приложения нет. Только таск второго.

Жмем Start, жмем Info:

Count: 1
Root: ru.startandroid.develop.p1161mngtasks1/.ActivityC
Top: ru.startandroid.develop.p1161mngtasks1/.ActivityC
——————
Count: 1
Root: ru.startandroid.develop.p1162mngtasks2/.MainActivity
Top: ru.startandroid.develop.p1162mngtasks2/.MainActivity

Свой таск для ActivityC cоздался.

singleInstance

singleInstance – Activity всегда одно в своем таске. Т.е. если вызывать ActivityC, то будет создан новый отдельный таск под него. И неважно — из ActivityB (таск первого приложения) или из MainActivity (таск второго) пришел вызов. Если же из ActivityC дальше вызвать ActivityD, то D поищет свой таск (например, с ранее открытыми A и B) и создастся в нем, а если не найдет то создаст новый.

Если есть желание, попробуйте применить этот режим для ActivityC и потестить самостоятельно.

После всех тестов не забудьте очистить в манифесте свойство launchMode для ActivityС и ActivityD, чтобы корректно работали дальнейшие примеры. И очистите таски.

Флаги для Intent

Флаги применяются к Intent с помощью метода addFlags. Эти флаги повлияют на поведение вызываемого Activity.

FLAG_ACTIVITY_NEW_TASK

FLAG_ACTIVITY_NEW_TASK — в хелпе пишут, что этот флаг аналогичен значению singleTask в launchMode. У меня почему-то не совсем так. Activity находит свой таск, но не ищет в этом таске себя, а просто создает новое Activity сверху.

FLAG_ACTIVITY_SINGLE_TOP

FLAG_ACTIVITY_SINGLE_TOP – аналогичен значению singleTop для launchMode.

FLAG_ACTIVITY_CLEAR_TOP

FLAG_ACTIVITY_CLEAR_TOP – ищет в таске создаваемое Activity. Если находит, то открывает, а все, что выше – закрывает. Можно сказать, что этот флаг в комбинации с FLAG_ACTIVITY_NEW_TASK является аналогом singleTask в launchMode.

FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET

FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET – помечает вызванное Activity. При следующем вызове таска из Home, это Activity и все вышерасположенные будут закрыты. В качестве примера можно привести почтовую программу. Вы открываете письмо, щелкаете на вложение и переходите в некую программу просмотра вложения. Затем сворачиваете приложение. Когда вы в следующий раз запустите почту, вы увидите верхнее Activity таска, т.е. просмотр вложения. А если вызывать просмотр вложения с вышеуказанным флагом, то при следующем запуске почты просмотр вложения будет закрыт и вы увидите письмо.

Читайте также:  Резервное копирование андроид самсунг где находится

Рассмотрим на примере. В MainActivity второго приложения перепишем метод onClick:

Будем вызывать ActivityC с этим флагом. Сохраняем, запускаем второе приложение. Жмем Start, открывается ActivityC, жмем еще раз Start, открывается ActivityD. Таск сейчас такой: Main-C-D.

Свернем приложение, нажав Home. Далее запускаем его с рабочего стола. Система находит таск и открывает его. На экране MainActivity второго приложения. Т.к. ActivityC было запущено с вышеуказанным флагом, оно и все вышестоящие Activity были закрыты при запуске приложения. В таске теперь только MainActivity.

FLAG_ACTIVITY_NO_HISTORY

FLAG_ACTIVITY_NO_HISTORY – Activity не будет сохранено в таске. Например, мы вызываем B с таким флагом из A. Далее из B вызываем C. Теперь жмем Назад и попадаем сразу в A, т.к. B не сохранилось в таске.

FLAG_ACTIVITY_REORDER_TO_FRONT

FLAG_ACTIVITY_REORDER_TO_FRONT – если Activity уже есть в таске оно переместится в топ. Например, есть таск A-B-C-D. Если D вызывает B с таким флагом, то таск станет таким A-C-D-B.

Пара флагов, появившихся с API Level 11. Используются совместно с FLAG_ACTIVITY_NEW_TASK.

FLAG_ACTIVITY_CLEAR_TASK

FLAG_ACTIVITY_CLEAR_TASK – таск для вызываемого Activity будет очищен, а вызываемое Activity станет в нем корневым. Сделаем пример.

В MainActivity второго приложения перепишем метод onClick:

Очистим таски. Запускаем первое приложение, жмем три раза Start, получаем A-B-C-D. Запускаем второе приложение, жмем Start, открывается ActivityC. Жмем Info:

Count: 1
Root: ru.startandroid.develop.p1161mngtasks1/.ActivityC
Top: ru.startandroid.develop.p1161mngtasks1/.ActivityC
——————
Count: 1
Root: ru.startandroid.develop.p1162mngtasks2/.MainActivity
Top: ru.startandroid.develop.p1162mngtasks2/.MainActivity

Таск первого приложения полностью очистился, в нем теперь только ActivityC.

FLAG_ACTIVITY_TASK_ON_HOME

FLAG_ACTIVITY_TASK_ON_HOME – таск для вызываемого Activity будет располагаться сразу после Home. Если из этого нового таска выходить кнопкой Назад, то попадешь не в предыдущий таск, а в Home. Сделаем пример.

В MainActivity второго приложения перепишем метод onClick:

Очистим таски. Запускаем второе приложение. Жмем Start. Открывается таск первого приложения, ActivityC. В нормальном режиме, если нажать сейчас Назад, то мы бы вернулись в таск второго приложения, в MainActivity. Но мы использовали флаг, поэтому нажимаем Назад и попадаем в Home.

Affinities

taskAffinity

Вернемся к атрибуту affinity. Его точное название – taskAffinity. Как я уже рассказал выше, этот атрибут используется для определения своего таска для Activity. По умолчанию для каждого Activity этот атрибут равен пакету приложения. Таск же принимает значение affinity от корневого Activity.

Чтобы лучше понять принцип, давайте реализуем пример. У нас есть первое приложение, которое при запуске использует таск с affinity = ru.startandroid.develop.p1161mngtasks1. Второе приложение использует таск с affinity = ru.startandroid.develop.p1162mngtasks2.

Если мы из второго приложения вызовем ActivityC с флагом FLAG_ACTIVITY_NEW_TASK, то ActivityC будет искать свой таск с affinity = ru.startandroid.develop.p1161mngtasks1. Найдет таск первого приложения и запустится там, либо, если такого таска пока нет, то само создаст такой таск.

Попробуем для ActivityC прописать какой-нибудь левый affinity, например: ru.startandroid.develop.p1163testaffinity. В этом случае таск первого приложения ему не подойдет, и он точно создаст свой таск. Давайте проверим. Пропишите affinity для ActivityC

Сохраняем и запускаем первое приложение, формируем таск A-B-C-D. Свернем первое приложение, запустим второе. Жмем Info:

Count: 1
Root: ru.startandroid.develop.p1162mngtasks2/.MainActivity
Top: ru.startandroid.develop.p1162mngtasks2/.MainActivity|
——————
Count: 4
Root: ru.startandroid.develop.p1161mngtasks1/.ActivityA
Top: ru.startandroid.develop.p1161mngtasks1/.ActivityD

Жмем Start во втором приложении, открылось ActivityC. Жмем Info:

Count: 1
Root: ru.startandroid.develop.p1161mngtasks1/.ActivityC
Top: ru.startandroid.develop.p1161mngtasks1/.ActivityC
——————
Count: 1
Root: ru.startandroid.develop.p1162mngtasks2/.MainActivity
Top: ru.startandroid.develop.p1162mngtasks2/.MainActivity
——————
Count: 4
Root: ru.startandroid.develop.p1161mngtasks1/.ActivityA
Top: ru.startandroid.develop.p1161mngtasks1/.ActivityD

К сожалению, я не знаю, как вытащить значение affinity для таска или его корневого Activity. Но четко видно, что для ActivityC не подошел таск первого приложения (из-за разных affinity), и оно выделилось в отдельный таск.

Очистите атрибут affinity для ActivityC и очистите таски.

allowTaskReparenting

У Activity есть атрибут allowTaskReparenting.Он позволяет перекидывать Activity из фоновых в активные таски.

Установим этот параметр для ActivityD

Во втором приложении перепишем onClick:

Все сохраняем, запускаем второе приложение. Жмем Start, получаем ActivityC, жмем Start получаем ActivityD.

Count: 3
Root: ru.startandroid.develop.p1162mngtasks2/.MainActivity
Top: ru.startandroid.develop.p1161mngtasks1/.ActivityD

Таск Main-C-D. Сворачиваем этот таск. Запускаем первое приложение (из Eclipse ,т.к. были изменения) и видим сразу ActivityD. Жмем Info:

Count: 2
Root: ru.startandroid.develop.p1161mngtasks1/.ActivityA
Top: ru.startandroid.develop.p1161mngtasks1/.ActivityD
——————
Count: 2
Root: ru.startandroid.develop.p1162mngtasks2/.MainActivity
Top: ru.startandroid.develop.p1161mngtasks1/.ActivityC

ActivityD, для которого мы указали атрибут allowTaskReparenting, перешло из фонового таска второго приложения в запущенный свой таск (первого приложения).

Очистка таска

Если пользователь долгое время не использует свернутый таск, то система его чистит, за исключением корневого Activity. Система ведет себя так исходя из предположения, что, если пользователь долго не возвращался к выполняемой задаче, то эта задача ему более не интересна.

Мы можем повлиять на это поведение системы. Существуют атрибуты для Activity:

alwaysRetainTaskState – если установлено в true для Activity, которое является корневым в таске, то этот таск сохранит свои Activity даже спустя долгое время

clearTaskOnLaunch – если установлено в true для Activity, которое является корневым в таске, то при каждом запуске таск очищается. Причем, именно при запуске, а не при выборе таска из списка последних.

finishOnTaskLaunch – аналогичен clearTaskOnLaunch, но действует для конкретного Activity. Например, включим этот атрибут для ActivityC. Запустим первое приложение и сформируем таск A-B-C-D. Свернем его и запустим снова первое приложение, получим таск A-B-D. ActivityC при новом запуске закрылось.

Большой получился материал. Сразу все это в голове, конечно, не уложится. Но, думаю, вполне пригодится как справка или памятка, когда понадобится задать нестандартное поведение для своего приложения.

На следующем уроке:

— создаем простой виджет
— разбираемся в его Lifecycle

Присоединяйтесь к нам в Telegram:

— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование

— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме

Источник

Оцените статью