Как вы используете Intent.FLAG_ACTIVITY_CLEAR_TOP, чтобы очистить стек активности?

Я прочитал несколько сообщений об использовании этого, но должен упустить что-то, поскольку он не работает для меня. Моя активность A имеет в манифесте startmode = "singleTop". Он начинает активность B, с launchmode = "singleInstance". Активность B открывает браузер и получает и убирает назад, поэтому он singleInstance. Я пытаюсь переопределить кнопку "Назад", чтобы пользователь был отправлен обратно на операцию "А", а затем может нажать "Назад", чтобы оставить активную операцию, а не вернуться к активности В снова.

// activity B
@Override
public boolean onKeyDown(int keyCode, KeyEvent event)  {
 if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.ECLAIR
  && keyCode == KeyEvent.KEYCODE_BACK
  && event.getRepeatCount() == 0) onBackPressed();
 return super.onKeyDown(keyCode, event);
}
@Override
public void onBackPressed() {
 startActivity(new Intent(this, UI.class)
 .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK));
 return;
}

После возврата из браузера стек... А, В, браузер, Б

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

Вместо этого он, кажется, меняет стек на... A, B, браузер, B, A ... как будто этих флагов там нет.

Я попытался вызвать finish() в действии B после startActivity, но затем кнопка back вернет меня обратно в браузер!

Что мне не хватает? Спасибо!

Ответ 1

@bitestar имеет правильное решение, но есть еще один шаг:

Он был скрыт в документах, однако вы должны изменить launchMode Activity на что-либо, кроме standard. В противном случае он будет уничтожен и воссоздан вместо reset вверху.

Ответ 2

Я начал работу A- > B- > C- > D. Когда кнопка возврата нажата на Activity DI, вы хотите перейти к Activity A. Так как A является моей отправной точкой, и поэтому уже в стеке все действия в верхней части A очищаются, и вы не можете вернуться к любой другой операции из A.

Это действительно работает в моем коде:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        Intent a = new Intent(this,A.class);
        a.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(a);
        return true;
    }
    return super.onKeyDown(keyCode, event);
}       

Ответ 3

Для этого я использую флаг FLAG_ACTIVITY_CLEAR_TOP для запуска Intent
(без FLAG_ACTIVITY_NEW_TASK)

и launchMode = "singleTask" в манифесте для запущенной активности.

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

Ответ 4

Хотя в этом вопросе уже есть достаточные ответы, я думал, что кто-то захочет узнать, почему этот флаг работает именно таким образом: вот что я нашел в Android-документация

Текущий исполняемый экземпляр действия B в приведенном выше примере либо получит новое намерение, которое вы начинаете здесь, в методе onNewIntent(), либо сам закончите и перезапустите с новым намерением.

Если он объявил свой режим запуска "множественным" (по умолчанию), и вы не установили FLAG_ACTIVITY_SINGLE_TOP в том же намерении, то он будет завершен и заново создан; для всех других режимов запуска или если FLAG_ACTIVITY_SINGLE_TOP установлен, этот Intent будет доставлен в текущий экземпляр onNewIntent().


Итак,
1. Измените launchMode Activity A на что-то еще из стандартного (т.е. singleTask или что-то еще). Тогда ваш флаг FLAG_ACTIVITY_CLEAR_TOP не перезапустит вашу активность A.

или,

2. Используйте Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP в качестве своего флага. Тогда он будет работать так, как вы пожелаете.

Ответ 5

Я знаю, что есть уже принятый ответ, но я не вижу, как это работает для OP, потому что я не думаю, что FLAG_ACTIVITY_CLEAR_TOP имеет смысл в его конкретном случае. Этот флаг относится только к действиям в той же самой задаче. Основываясь на его описании, каждое действие находится в собственной задаче: A, B и браузере.

Что-то, что может его отбросить, это то, что A является singleTop, когда он должен быть singleTask. Если A является одноточечным, а B запускает A, тогда будет создан новый A, потому что A не находится в задаче B. Из документации для singleTop:

"Если экземпляр активности уже существует в верхней части текущей задачи, система перенаправляет намерение на этот экземпляр..."

Так как B запускает A, текущая задача - это задача B, которая для singleInstance и, следовательно, не может включать A. Используйте singleTask для достижения желаемого результата там, потому что тогда система найдет задачу с A и выполнит эту задачу на переднем плане.

Наконец, после того, как B запустил A, и пользователь нажимает A, OP не хочет видеть ни B, ни браузер. Чтобы достичь этого, вызов finish() в B правильный; снова FLAG_ACTIVITY_CLEAR_TOP не будет удалять другие действия в задаче A, потому что другие его действия выполняются в разных задачах. Часть, которую он отсутствовала, заключается в том, что B также должен использовать FLAG_ACTIVITY_NO_HISTORY при запуске намерения для браузера. Примечание:, если браузер уже запущен до начала запуска приложения OP, то, конечно, вы увидите браузер, когда будете нажимать обратно с A. Поэтому, чтобы действительно проверить это, обязательно вернитесь из браузера перед запуском приложения.

Ответ 6

FLAG_ACTIVITY_NEW_TASK является проблемой здесь, которая инициирует новую задачу. Просто удалите ее, и все готово.

Хорошо, я рекомендую вам прочитать, что делает каждый флаг перед тем, как работать с ними.

Прочитайте этот и Intent Flags здесь

Ответ 7

Изначально у меня также была проблема с запуском FLAG_ACTIVITY_CLEAR_TOP. В конце концов я получил его для работы, используя его значение (0x04000000). Поэтому выглядит проблема Eclipse/компилятора. Но, к сожалению, возобновляемая деятельность перезапускается, чего я не хочу. Таким образом, похоже, что нет простого решения.

Ответ 8

я назвал activity_name.this.finish() после начала нового намерения, и это сработало для меня.

I tried "FLAG_ACTIVITY_CLEAR_TOP" and "FLAG_ACTIVITY_NEW_TASK"

Но это не сработает для меня... Я не предлагаю это решение для использования, но если флаг установки не будет работать для вас, вы можете попробовать это. Но все же я рекомендую не использовать его

Ответ 9

Добавить андроид: noHistory = "true" в файле манифеста.

<manifest >
        <activity
            android:name="UI"
            android:noHistory="true"/>

</manifest>

Ответ 10

Я использую три флага для решения проблемы:

intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|
                Intent.FLAG_ACTIVITY_CLEAR_TASK | 
                Intent.FLAG_ACTIVITY_NEW_TASK);