1 сентября 2014 г.

Задачи и обратный стек (Tasks and back stack). Часть 14 (практика)

Возвращаемся к нашим задачам и стекам после долгого перерыва Улыбка

Мы продолжаем разбирать эту тему http://pr0andr0id.blogspot.ru/2014/04/tasks-and-back-stack-4.html

Мы закончили рассмотрение изменения поведения активности при помощи launchMode и теперь переходим к определению способов запуска при помощи Intent флагов.

Как выяснилось в стандартном описании launchMode отражены не все особенности и тонкости поведения активностей при использовании launchMode. То же самое можно сказать и про Intent флаги. Описание в альма-матер дано далеко не полное. Эксперименты позволяют понять эту тему лучше и глубже. И Активности ведут себя не всегда так как можно было бы ожидать, так что практика критерий истины.

И так пристумиссс…

Мои приложения AP0003 и AP0004 продолжают мутировать и эволюционировать. Напомню что в приложении AP0003 Активность В имеет launchMode = standard, то есть обычный метод запуска.

В приложении AP0004 в Активности А добавлена кнопка запуска активности В из AP0003 с флагом FLAG_ACTIVITY_NEW_TASK

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

F0001

Нажмем кнопку Info и посмотрим логи

F0002

В логах видно что запустилась Активность А в задаче 35. И у нас в задаче 35 сейчас одна Активность А.

Теперь нажмем кнопку Start B AP0003 NEW TASK flag

F0003

Запустилась Активность В из приложения АР0003 в задаче 36. Здесь пока все как в описании в альма-матер. Активность запустилась в новой задаче. Напомню, что если бы мы не использовали флаг FLAG_ACTIVITY_NEW_TASK, то активность В из приложения АР0003 запустилась бы в задаче 35, так как у нее launchMode=standard. Но флаг FLAG_ACTIVITY_NEW_TASK имеет приоритет над launchMode и переопределяет как должна быть запущена Активность.

Нажмем кнопку Info

F0004

Из логов видно что в задаче 36 существует сейчас одна активность В, а в задаче 35 одна активность А. Пока все правильно как и было описано в альма-матер.

Теперь нажмем кнопку ОБРАТНО и попадем в приложение АР0004 задача 35.

F0005

Обращаем внимание что Активность сообщает нам что она уже была запущена. И снова жмем кнопку обратно чтобы выйти из АР0004.

Теперь запустим сперва приложение АР0003

F0006

и нажмем кнопочку Start Activity B

F0007

Видим что обе Активности А и В запущены в задаче 58 и в ее стеке сейчас две Активности А-В. Нажмем Info чтобы в этом убедиться.

F0008

Логи это подтверждают

Теперь введем любой текст в поле ввод текста, чтобы идентифицировать нашу Активность В.

F0009

И нажмем кнопку HOME

Теперь запустим приложение AP0004

F0010

АР0004 запустилось в задаче 59. И так у нас сейчас запущено два приложения АР0003 задача 58 и в ней две Активности А-В и приложение АР0004 с одной Активностью А.

Нажмем Info чтобы убедиться

F0011

Убедились Улыбка

То есть у нас есть задача 58 в которой уже есть запущенная Активность В. Судя из описания в альма-матер

FLAG_ACTIVITY_NEW_TASK
Start the activity in a new task. If a task is already running for the activity you are now starting, that task is brought to the foreground with its last state restored and the activity receives the new intent in onNewIntent().
This produces the same behavior as the "singleTask" launchMode value, discussed in the previous section.

Напомню что Активность В у нас уже существует в задаче 58, что собственно видно из логов и того что мы проделали.

То есть, ожидается если мы сейчас нажмем на кнопку запуска Активности В из Активности А приложения АР0004, то мы должны будем переключится на уже существующую Активность В, приложения АР0003, НО ЭТО НЕ ТАК!

Нажимаем кнопку Start B AP0003 NEW TASK flag

F0012

Мы видим что, да мы попали в задачу 58 и была запущена Активность В, НО ЭТО НОВЫЙ ЭКЗЕМПЛЯР Активности В. То есть стек задачи 58 сейчас имеет вид А-В-В. В задаче 58 сейчас ТРИ Активности. Мы видим что переключения на уже существующую Активность В не произошло, а вместо этого в стеке задачи 58 была создана еще одна Активность В. Чтобы убедиться в этом нажмем кнопку Info

F0013

Из логов виден создание нового экземпляра Активности В, а так же количество Активностей в задаче 58.

Теперь нажмем кнопку ОБРАТНО

F0014

Из скрина видно что мы попали в нашу Активность В, которую запускали из приложения AP0003. Это видно из сообщения о том что Активность уже была запущена а так же из текста который мы ввели в текстовое поле. Хотя счетчик показывает что в задаче 3 Активности, он просто глючит. Его надо подфиксить, если будет время и желание займусь. На самом деле в задаче 58 сейчас две Активности и стек имеет вид А-В. Нажмем кнопку Info чтобы в этом убедиться.

F0015

Из логов видно что в задаче 58 была уничтожена верхняя Активность В и восстановлена вторая Активность В. И стек задачи 58 сейчас имеет вид А-В.

Единственное что произошло как в описании из альма-матер это переключение на стек задачи 58. Напомню что Активность В была запущена из приложения АР0004, и если мы ожидали бы нормальное поведение, то по кнопке ОБРАТНО мы должны были бы попасть в приложение АР0004, но мы остались в стеке приложения АР0003.

Теперь если мы нажмем еще раз кнопку ОБРАТНО то попадем в Активность А приложения АР0003.

F0016

И только если сейчас нажмем кнопку ОБРАТНО то попадем в приложение АР0004 в его Активность А.

F0017

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

Но и это еще не все Улыбка 

Поведение описанное в альма-матер может наблюдаться только в одном случае из множества возможных

Сейчас приведу этот пример

Запускаем АР0004

F0018

Активность запустилась в задаче 81. Теперь запускаем Активность В в приложении АР0003 и вводим какой-нибудь текст в поле.

F0019

Видим что Активность В приложения АР0003 была запущена в задаче 82. То есть в задачах 81 и 82 у нас по одной Активности. В задаче 81 Активность А, в задаче 82 Активность В.

Теперь нажимаем кнопку HOME и запускаем АР0004

F0020

Обращаем внимание что Активность А нам сообщает что она уже была запущена! То есть мы попали в уже существующий экземпляр Активности А. Что собственно правильно и логично. Теперь жмем кнопку Start B AP0003 NEW Task flag.

F0021

И видим что мы попали в уже существующий экземпляр Активности В задачи 82. То есть только в одном случае из множества возможных мы получили поведение описанное в альма-матер. Это происходит только тогда, когда Активность В была изначально запущена из приложения АР0004 и только в случае если в данные момент она сейчас находится на вершине стека в своей задаче.

Чтобы подтвердить это нажмем кнопку Start Activity C и введем в Активности С какой-нибудь текст.

F0022

То есть стек задачи 82 содержит две Активности В и С и имеет вид В-С. А стек задачи 81 содержит одну Активность А. Нажмем кнопку Info чтобы в этом убедиться

F0023

Убедились Улыбка

Теперь нажмем кнопку HOME и снова запустим приложение АР0004

F0020

которое нам сообщит что оно уже было запущено и нажмем кнопку Start B AP0003 NEW TASK flag

F0024

И мы попали в существующий экземпляр Активности С, хотя запускали Активность В! То есть мы попали на вершину стека задачи 82.

Чтобы убедиться в этом еще раз и основательно нажмем Start Activity D введем текст в поле

F0025

Видим что Активность была запущена в первый раз. То есть сейчас стек задачи 82 содержит ТРИ Активности и имеет вид В-С-D. Теперь нажмем Start Activity A и введем какой либо текст.

F0026

Сейчас стек задачи 82 содержит четыре Активности и имеет вид B-C-D-A. Нажмем кнопку Info чтобы в этом убедиться.

F0027

Нажмем кнопку HOME и запустим приложение AP0004

F0020

и снова нажмем Start B AP0003 NEW TASK flag

F0028

И мы снова попали не в Активность В как предполагалось, а попали на вершину стека задачи в которой существует Активность В. И полностью переключились на стек данной задачи. То есть если мы сейчас нажмем кнопку ОБРАТНО мы не попадем в Активность А задачи 81 из которой мы только что сюда попали. А попадем в Активность D задачи 82.

И так жмем ОБРАТНО

F0029

Обращаем внимание что Активность сообщает что она уже была запущена и мы так же видим введенный нами текст. Жмем еще раз ОБРАТНО

F0030

И еще раз ОБРАТНО

F0031

И вот только сейчас если мы нажмем ОБРАТНО мы попадем в Активность А приложения АР0004

F0020

В данном примере мы убедились, что если запускаемый экземпляр Активности В уже существует в другой задаче, то новый экземпляр НЕ СОЗДАЕТСЯ, а происходит переключение на вершину стека этой задачи. И это происходило только в том случае если ИЗНАЧЛЬНО мы запускали Активность В приложения АР0003 из приложения АР0004.

Если же экземпляр Активности В изначально будет запущен из приложения АР0003 то есть уже будет существовать в задаче этого приложения, то если мы попытаемся запустить Активность В из приложения АР0004, то будет создан новый экземпляр Активности В в той задаче в которой он уже существует (в нашем случае в задаче приложения АР0003).

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

Запускаем АР0003 и вводим любой текст

F0032

Жмем Start Activity B и тоже вводим любой текст

F0033

Жмем Start Activity C и вводим любой текст

F0034

Теперь нажмем кнопку HOME и запустим приложение АР0004

F0035

И так у нас есть две задачи 94 и 95, в 94 задаче приложения АР0003 стек имеет вид A-B-C (содержит три Активности). То есть Активность В уже существует и находится между А и С. Теперь запустим Активность В из приложения АР0004

F0036

То есть в данном случае создался НОВЫЙ экземпляр Активности В. И стек задачи 94 сейчас содержит 4 Активности и имеет вид А-В-С-В. Нажмем кнопку Info чтобы в этом убедиться

F0037

Таки убедились…

Если сейчас нажмем кнопку обратно то окажемся в Активности С приложения АР0003 задачи 94.

F0038

Счетчик на активности подглючивает но если нажать Info то убедимся что сейчас в задаче 94 содержится 3 Активности и стек имеет вид А-В-С.

F0039

Жмем еще раз ОБРАТНО

F0040

И видим уже существующую Активность В. Стек задачи 94 сейчас содержит две Активности и имеет вид А-В.

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

Жмем кнопку ОБРАТНО

F0041

И оказываемся в Активности А приложения АР0003

Еще раз ОБРАТНО и мы в Активности А приложения АР0004

F0042

Такое поведение так же надо учитывать при разработке приложений.

Комментариев нет:

Отправить комментарий