Это классическая «черта» разработки для 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;
}
}