Что означает «видимость» в жизненном цикле деятельности? OnPause vs onStop? - PullRequest
3 голосов
/ 27 декабря 2011

Жизненный цикл деятельности вызывает у меня головную боль.Документация по http://developer.android.com/reference/android/app/Activity.html настолько чертовски неоднозначна, когда описывает концепцию видимости, поэтому я не могу понять, когда onStop() называется vs onPause().

Сравните следующие два утвержденияиз документации:

(взято справа под диаграммой жизненного цикла)

Методы onStart() и onStop() можно вызывать несколько раз, так какдействие становится видимым и скрытым для пользователя.

против

(далее в синей таблице со столбцами "убиваемых")

onPause() Вызывается, когда система собирается возобновить предыдущее действие.

Что я понял из первой цитаты, это то, что onStop() вызывается для действия A когда A скрыто.Я думаю, что «скрытый» относится к тому моменту, когда другое действие B было возобновлено и полностью охватывает действие A.Но во второй цитате говорится, что onPause() вызывается, когда начинается возобновление другого действия.Не будет ли это полностью скрывать деятельность А?Похоже, что в обоих случаях эта деятельность A становится «скрытой», не так ли?Согласно моей вероятной ошибочной интерпретации, onPause() и onStop() вызываются в идентичных ситуациях.

Документация также кажется разной между скрытым (вызывается onStop()) и частичной видимостью (onPause()вызывается).Но когда деятельность все еще частично видна?Они имеют в виду буквально?Или может ли действие все еще считаться «частично видимым», когда оно запустило новое действие (действие вызывает startActivityForResult и запускает действие выбора даты), которое охватывает весь экран?Конечно, активность не будет вызвана onStop?Он должен получить результат в любой момент!

Так что я пытаюсь выяснить, что я не получаю.Я понимаю, что вызов onPause гарантирован.Это может быть, когда действие A теряет фокус (устройство переходит в спящий режим, блокировку экрана и т. Д.), Другое действие B выходит на передний план (где действие B может быть инициировано или не инициировано действием A).Но в какой момент onStop() вызывается для действия A?

Имеет ли значение, сколько действий было сложено поверх действия A в стеке действий?Есть ли два разных определения «видимости» в игре?

Извините за стену текста, но я действительно расстроен: S

Итак, вопрос стоит: именно в каких ситуацияхактивность считается "скрытой", так что onStop() вызывается для нее?

РЕДАКТИРОВАТЬ:

Я вставил уведомления Toast в каждый метод onX и обнаружил некоторые дополнительные странности:

  1. При нажатии кнопки «Домой» всегда вызывается onStop ().Но запуск приложения не вызовет onRestart().Вместо этого он вызывает onCreate().Это кажется странным для меня, но хорошо ...
  2. Когда действие "USB Mass Storage" запускается поверх основного действия, вызывается onStop().А при выходе из режима хранения USB и возвращении к основному действию вызывается onRestart() вместо onCreate().
  3. Когда устройство переходит в спящий режим и активируется, оно проходит только черезonPause() и onResume() цикл.

Последний пункт был ожидаем (хотя я не могу вписать его в диаграмму жизненного цикла).Но что случилось с 1. и 2.?

В первом пункте я ожидал вызова на onRestart() при повторном запуске активности.Почему он отменил действие и вместо этого вызвал onCreate()? 1087 *

И взглянем на пункт № 2:В соответствии с документацией: когда «перед деятельностью появляется другая деятельность», следует вызвать onPaused().Разве это не то, что произошло, когда активность USB-накопителя поднялась?Он не вызывал onPause(), он прошел цикл onStop() - OnRestart()!Очевидно, что в документации не учитывается тот случай, когда «перед деятельностью появляется другая деятельность».Так что же на самом деле произошло?

Ответы [ 2 ]

2 голосов
/ 29 декабря 2011

Хорошо, я думаю, что у меня есть это сейчас.

1

Ключом к первому пункту была эта ссылка:

http://code.google.com/p/android/issues/detail?id=2373

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

Я разместил код в верхней части метода onCreate, чуть ниже вызова super.onCreate:

if (!isTaskRoot()) {
    final Intent intent = getIntent();
    final String intentAction = intent.getAction();
    if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) &&
            intentAction != null && intentAction.equals(Intent.ACTION_MAIN)) {
        finish(); return;
    }
}

Обратите внимание, что я добавил оператор return после финиша, чтобы остальная часть метода onCreate не выполнялась в случае обнаружения ошибки.

2. & 3.

Ключом ко второму и третьему пунктам были эти две ссылки:

http://answers.oreilly.com/topic/2692-android-programming-understanding-the-activity-life-cycle/

Как сделать Активность, не охватывающую весь экран

Оказывается, что «видимость» действительно буквально! Поэтому, когда в документации говорится, что «другое действие стоит перед действием», действие, стоящее за перемещенным действием, все еще частично видно. Это означает, что менеджер активности Android должен проверить, является ли активная операция полноэкранным действием или нет: если это так, onStop() вызывается для предыдущего действия. Если нет, то вместо предыдущей операции вызывается onPaused().

Это тривиально объясняет, почему диспетчер USB-накопителя вызвал onStop().

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

(см. Вторую ссылку о том, как выполнять не полноэкранные операции)

Интересно, что раскрывающееся окно (с уведомлениями) не вызывает onPause() (и при этом оно не вызывает onStop()), даже если бы оно имело смысл как не полноэкранное действие. Это должно быть какое-то исключение, которое я буду расследовать самостоятельно.

Это также означает, что цикл onStop()-onRestart(), вероятно, более распространен, чем цикл onPause()-onResume() (хотя оба должны учитываться), поскольку действия, вероятно, чаще всего являются полноэкранными (лично я думал, что документация указала обратное: что onPause-onResume было более распространенным, но, возможно, это только я).

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

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

Но это выходит за рамки этого вопроса.

0 голосов
/ 02 декабря 2016

Наконец-то отследили это: вы можете определить раскрытие строки состояния, используя onWindowFocusChanged ()

как использовать метод OnWindowFocusChanged

...