Это классический «гоча» разработки для Android. Здесь есть две проблемы:
- Существует небольшая ошибка в Android Framework, которая значительно усложняет управление стеком приложений во время разработки, по крайней мере, в старых версиях (не совсем уверенно, если / когда / как это было исправлено). Я буду обсуждать эту ошибку ниже.
- «Нормальный» или предполагаемый способ решения этой проблемы сам по себе довольно сложен из-за двойственности onPause / onResume и onSaveInstanceState / onRestoreInstanceState
Просматривая все эти темы, я подозреваю, что большую часть времени разработчики говорят об этих двух разных проблемах одновременно ... отсюда и вся путаница и сообщения о том, что «это не работает для меня».
Во-первых, чтобы прояснить «предполагаемое» поведение: onSaveInstance и onRestoreInstance хрупки и только для переходного состояния. Предполагаемое использование (afaict) состоит в том, чтобы обрабатывать Активный отдых, когда телефон поворачивается (изменение ориентации). Другими словами, предполагаемое использование - это когда ваша активность все еще логически «наверху», но все равно должна быть переоценена системой. Сохраненный Bundle не сохраняется вне процесса / memory / gc, поэтому вы не можете действительно полагаться на это, если ваша деятельность переходит в фоновый режим. Да, возможно, память вашей Деятельности переживет свое путешествие в фоновый режим и избежит GC, но это ненадежно (и не предсказуемо).
Поэтому, если у вас есть сценарий, в котором есть значимый «прогресс пользователя» или состояние, которое должно сохраняться между «запусками» вашего приложения, руководство должно использовать onPause и onResume. Вы должны выбрать и подготовить постоянный магазин самостоятельно.
НО - есть очень запутанная ошибка, которая усложняет все это. Подробности здесь:
http://code.google.com/p/android/issues/detail?id=2373
http://code.google.com/p/android/issues/detail?id=5277
По сути, если ваше приложение запускается с флагом SingleTask, а затем вы запускаете его из главного экрана или из меню запуска, то этот последующий вызов создаст НОВУЮ задачу ... у вас фактически будет два разных экземпляра вашего приложения. населяет один и тот же стек ... что очень странно и очень быстро. Кажется, это происходит, когда вы запускаете свое приложение во время разработки (например, из Eclipse или Intellij), поэтому разработчики часто сталкиваются с этим. Но также через некоторые механизмы обновления магазина приложений (так что это также влияет на ваших пользователей).
Я боролся с этими темами в течение нескольких часов, прежде чем понял, что моей главной проблемой была эта ошибка, а не предполагаемое поведение фреймворка. Отличная рецензия иобходной путь (ОБНОВЛЕНИЕ: см. Ниже), кажется, от пользователя @kaciula в этом ответе:
Поведение нажатия клавиши «Домой»
ОБНОВЛЕНИЕ Июнь 2013 : Несколько месяцев спустя я наконец нашел «правильное» решение. Вам не нужно управлять какими-либо флагами StarApp с сохранением состояния самостоятельно, вы можете обнаружить это из фреймворка и соответствующим образом внести залог. Я использую это в начале моего LauncherActivity.onCreate:
if (!isTaskRoot()) {
Intent intent = getIntent();
String action = intent.getAction();
if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) && action != null && action.equals(Intent.ACTION_MAIN)) {
finish();
return;
}
}