Возвращаемся к нашим задачам и стекам после долгого перерыва
Мы продолжаем разбирать эту тему 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
Нажмем кнопку Info и посмотрим логи
В логах видно что запустилась Активность А в задаче 35. И у нас в задаче 35 сейчас одна Активность А.
Теперь нажмем кнопку Start B AP0003 NEW TASK flag
Запустилась Активность В из приложения АР0003 в задаче 36. Здесь пока все как в описании в альма-матер. Активность запустилась в новой задаче. Напомню, что если бы мы не использовали флаг FLAG_ACTIVITY_NEW_TASK, то активность В из приложения АР0003 запустилась бы в задаче 35, так как у нее launchMode=standard. Но флаг FLAG_ACTIVITY_NEW_TASK имеет приоритет над launchMode и переопределяет как должна быть запущена Активность.
Нажмем кнопку Info
Из логов видно что в задаче 36 существует сейчас одна активность В, а в задаче 35 одна активность А. Пока все правильно как и было описано в альма-матер.
Теперь нажмем кнопку ОБРАТНО и попадем в приложение АР0004 задача 35.
Обращаем внимание что Активность сообщает нам что она уже была запущена. И снова жмем кнопку обратно чтобы выйти из АР0004.
Теперь запустим сперва приложение АР0003
и нажмем кнопочку Start Activity B
Видим что обе Активности А и В запущены в задаче 58 и в ее стеке сейчас две Активности А-В. Нажмем Info чтобы в этом убедиться.
Логи это подтверждают
Теперь введем любой текст в поле ввод текста, чтобы идентифицировать нашу Активность В.
И нажмем кнопку HOME
Теперь запустим приложение AP0004
АР0004 запустилось в задаче 59. И так у нас сейчас запущено два приложения АР0003 задача 58 и в ней две Активности А-В и приложение АР0004 с одной Активностью А.
Нажмем Info чтобы убедиться
Убедились
То есть у нас есть задача 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
Мы видим что, да мы попали в задачу 58 и была запущена Активность В, НО ЭТО НОВЫЙ ЭКЗЕМПЛЯР Активности В. То есть стек задачи 58 сейчас имеет вид А-В-В. В задаче 58 сейчас ТРИ Активности. Мы видим что переключения на уже существующую Активность В не произошло, а вместо этого в стеке задачи 58 была создана еще одна Активность В. Чтобы убедиться в этом нажмем кнопку Info
Из логов виден создание нового экземпляра Активности В, а так же количество Активностей в задаче 58.
Теперь нажмем кнопку ОБРАТНО
Из скрина видно что мы попали в нашу Активность В, которую запускали из приложения AP0003. Это видно из сообщения о том что Активность уже была запущена а так же из текста который мы ввели в текстовое поле. Хотя счетчик показывает что в задаче 3 Активности, он просто глючит. Его надо подфиксить, если будет время и желание займусь. На самом деле в задаче 58 сейчас две Активности и стек имеет вид А-В. Нажмем кнопку Info чтобы в этом убедиться.
Из логов видно что в задаче 58 была уничтожена верхняя Активность В и восстановлена вторая Активность В. И стек задачи 58 сейчас имеет вид А-В.
Единственное что произошло как в описании из альма-матер это переключение на стек задачи 58. Напомню что Активность В была запущена из приложения АР0004, и если мы ожидали бы нормальное поведение, то по кнопке ОБРАТНО мы должны были бы попасть в приложение АР0004, но мы остались в стеке приложения АР0003.
Теперь если мы нажмем еще раз кнопку ОБРАТНО то попадем в Активность А приложения АР0003.
И только если сейчас нажмем кнопку ОБРАТНО то попадем в приложение АР0004 в его Активность А.
То есть практика показала что описание данное в альма-матер верно лишь отчасти. То есть даже если запускаемая Активность уже существует в какой-либо задаче, то переключения на нее не происходит, а вместо этого создается новый экземпляр Активности в этой задаче и происходит переключение на стек этой задачи.
Но и это еще не все
Поведение описанное в альма-матер может наблюдаться только в одном случае из множества возможных
Сейчас приведу этот пример
Запускаем АР0004
Активность запустилась в задаче 81. Теперь запускаем Активность В в приложении АР0003 и вводим какой-нибудь текст в поле.
Видим что Активность В приложения АР0003 была запущена в задаче 82. То есть в задачах 81 и 82 у нас по одной Активности. В задаче 81 Активность А, в задаче 82 Активность В.
Теперь нажимаем кнопку HOME и запускаем АР0004
Обращаем внимание что Активность А нам сообщает что она уже была запущена! То есть мы попали в уже существующий экземпляр Активности А. Что собственно правильно и логично. Теперь жмем кнопку Start B AP0003 NEW Task flag.
И видим что мы попали в уже существующий экземпляр Активности В задачи 82. То есть только в одном случае из множества возможных мы получили поведение описанное в альма-матер. Это происходит только тогда, когда Активность В была изначально запущена из приложения АР0004 и только в случае если в данные момент она сейчас находится на вершине стека в своей задаче.
Чтобы подтвердить это нажмем кнопку Start Activity C и введем в Активности С какой-нибудь текст.
То есть стек задачи 82 содержит две Активности В и С и имеет вид В-С. А стек задачи 81 содержит одну Активность А. Нажмем кнопку Info чтобы в этом убедиться
Убедились
Теперь нажмем кнопку HOME и снова запустим приложение АР0004
которое нам сообщит что оно уже было запущено и нажмем кнопку Start B AP0003 NEW TASK flag
И мы попали в существующий экземпляр Активности С, хотя запускали Активность В! То есть мы попали на вершину стека задачи 82.
Чтобы убедиться в этом еще раз и основательно нажмем Start Activity D введем текст в поле
Видим что Активность была запущена в первый раз. То есть сейчас стек задачи 82 содержит ТРИ Активности и имеет вид В-С-D. Теперь нажмем Start Activity A и введем какой либо текст.
Сейчас стек задачи 82 содержит четыре Активности и имеет вид B-C-D-A. Нажмем кнопку Info чтобы в этом убедиться.
Нажмем кнопку HOME и запустим приложение AP0004
и снова нажмем Start B AP0003 NEW TASK flag
И мы снова попали не в Активность В как предполагалось, а попали на вершину стека задачи в которой существует Активность В. И полностью переключились на стек данной задачи. То есть если мы сейчас нажмем кнопку ОБРАТНО мы не попадем в Активность А задачи 81 из которой мы только что сюда попали. А попадем в Активность D задачи 82.
И так жмем ОБРАТНО
Обращаем внимание что Активность сообщает что она уже была запущена и мы так же видим введенный нами текст. Жмем еще раз ОБРАТНО
И еще раз ОБРАТНО
И вот только сейчас если мы нажмем ОБРАТНО мы попадем в Активность А приложения АР0004
В данном примере мы убедились, что если запускаемый экземпляр Активности В уже существует в другой задаче, то новый экземпляр НЕ СОЗДАЕТСЯ, а происходит переключение на вершину стека этой задачи. И это происходило только в том случае если ИЗНАЧЛЬНО мы запускали Активность В приложения АР0003 из приложения АР0004.
Если же экземпляр Активности В изначально будет запущен из приложения АР0003 то есть уже будет существовать в задаче этого приложения, то если мы попытаемся запустить Активность В из приложения АР0004, то будет создан новый экземпляр Активности В в той задаче в которой он уже существует (в нашем случае в задаче приложения АР0003).
Сейчас быстренько приведу пример последнего утверждения
Запускаем АР0003 и вводим любой текст
Жмем Start Activity B и тоже вводим любой текст
Жмем Start Activity C и вводим любой текст
Теперь нажмем кнопку HOME и запустим приложение АР0004
И так у нас есть две задачи 94 и 95, в 94 задаче приложения АР0003 стек имеет вид A-B-C (содержит три Активности). То есть Активность В уже существует и находится между А и С. Теперь запустим Активность В из приложения АР0004
То есть в данном случае создался НОВЫЙ экземпляр Активности В. И стек задачи 94 сейчас содержит 4 Активности и имеет вид А-В-С-В. Нажмем кнопку Info чтобы в этом убедиться
Таки убедились…
Если сейчас нажмем кнопку обратно то окажемся в Активности С приложения АР0003 задачи 94.
Счетчик на активности подглючивает но если нажать Info то убедимся что сейчас в задаче 94 содержится 3 Активности и стек имеет вид А-В-С.
Жмем еще раз ОБРАТНО
И видим уже существующую Активность В. Стек задачи 94 сейчас содержит две Активности и имеет вид А-В.
То есть мы убедились что в данном случае был создан еще один экземпляр Активности В, правда в задаче где Активность В уже существовала, а не произошло передачи фокуса в существующий экземпляр Активности В.
Жмем кнопку ОБРАТНО
И оказываемся в Активности А приложения АР0003
Еще раз ОБРАТНО и мы в Активности А приложения АР0004
Такое поведение так же надо учитывать при разработке приложений.
Комментариев нет:
Отправить комментарий