Странности жизненного цикла Android с singleTop и сервисом переднего плана?

Вот сценарий:

  • Начать действие А
  • Действие A запускает службу S
  • Служба S работает в режиме переднего плана и отображает уведомление, которое при нажатии переводит пользователя в действие B (которое имеет launchMode="singleTop")
  • Активность B появляется
  • Нажмите ДОМОЙ
  • Войдите в DDMS и завершите процесс своего приложения, чтобы имитировать, что ваше приложение умерло (нажмите красную кнопку STOP)
  • Android скажет «Перепланирование аварийного сервиса через 5000 мс» (иногда дольше)
  • Служба S перезапускается, и отображается уведомление.
  • Нажмите значок уведомления, когда служба перезапустится...

... в это время Android восстановит обе операции A и B из-за того, что процесс неожиданно завершился. Но, несмотря на то, что Activity B является singleTop, Android вызовет его СНОВА, потому что пользователь щелкнул уведомление. Это приводит к тому, что A -> B -> B находится в стеке действий. Нажав назад, вы снова вернетесь к первому восстановленному экземпляру Activity B.

Может ли кто-нибудь из команды Android прояснить, что происходит за кулисами и как этого избежать? Каков наилучший способ имитировать, что Android убил процесс из-за нехватки памяти? Достаточно ли нажатия STOP из DDMS или это пограничный случай, и этого никогда не должно происходить при нормальных обстоятельствах?

В чем разница между «Принудительной остановкой» из «Настройки» -> «Приложения» и «STOP» из DDMS?

Заранее спасибо!


person dnkoutso    schedule 01.12.2011    source источник


Ответы (3)


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

Проверьте свое приложение, чтобы убедиться, что оно не вызывает startActivity() при повторной инициализации или других подобных действиях. Посмотрите в журнале, какие действия запускаются и какие намерения используются. Используйте «adb shell dumpsys activity», чтобы увидеть, как выглядит текущий стек активности. Может быть, вы очистили сходство задач, поэтому вторая активность B запускается в своей собственной задаче (в этом случае singleTop не окажет никакого влияния)?

Кроме того, очень трудно помочь людям, если вы не включаете полезную информацию о том, что вы делаете. Соответствующие операторы журнала на разных этапах, состояние стека действий, отображаемое «активностью дампа оболочки adb» и т. д.

person hackbod    schedule 09.12.2011
comment
Диана, я дам вам гораздо более подробный ответ по этому вопросу. Я использовал «активность dumpsys оболочки adb», и нет двух запущенных задач. Одна и та же активность B дважды находится поверх задачи, несмотря на наличие singleTop в манифесте. Я отмечу этот ответ как правильный и, возможно, обновлю его, когда получу демо-приложение. - person dnkoutso; 11.12.2011
comment
Диана, см. прикрепленную демонстрацию sendspace.com/file/vn8y8j. У меня есть скриншоты, которые дважды показывают ActivityB в одной и той же задаче. - person dnkoutso; 13.12.2011
comment
Если вы запускаете действие с другим намерением, отличным от того, которое изначально использовалось для запуска задачи, то новый экземпляр действия будет создан поверх существующей задачи, потому что вы просите сделать что-то отличное от исходной задачи. Подумайте об этом, как если бы вы сначала запустили его с ACTION_VIEW одного URI, а затем с ACTION_VIEW другого URI. Когда вы запускаете второе действие, необходимо запустить новый экземпляр поверх существующей задачи, чтобы правильно отобразить другое намерение. - person hackbod; 10.02.2012
comment
Наконец-то увидел этот комментарий. Спасибо, Диана, это звучит разумно! Я проверю и посмотрю, как с этим справиться. - person dnkoutso; 12.04.2012

Я не слишком уверен в подробных различиях между STOP в DDMS и Force Stop, но я почти уверен, что DDMS обходит некоторые внутренние функции Android, которые будет выполнять Force Stop, поскольку я не помню, чтобы Android когда-либо повторно инициализировал мои действия, когда я сделал принудительную остановку. Если это правда, то я подозреваю, что то, что вы видите, является результатом двух разных задач, запущенных Android: одна для старых, убитых действий, а другая для перезапуска убитой службы. Вы можете проверить эту теорию, установив флаг «singleTask» и проверив, происходит ли такое же поведение. Надеюсь это поможет.

person ACrazyOldMan    schedule 07.12.2011

Наличие A -> B -> B возможно, даже если B является singleTop: для ситуации, когда B запускается как другая задача. В случае, если на самом деле есть 2 стека: A -> B и B

person Paul Verest    schedule 05.02.2015