Android: очистить задний стек


330

В Android у меня есть некоторые действия, скажем, A, B, C.

В A я использую этот код, чтобы открыть B:

Intent intent = new Intent(this, B.class);
startActivity(intent);

В B я использую этот код, чтобы открыть C:

Intent intent = new Intent(this, C.class);
startActivity(intent);

Когда пользователь нажимает кнопку в C, я хочу вернуться к A и очистить задний стек (закрыть B и C). Поэтому, когда пользователь нажимает кнопку возврата B и C не отображаются, я пробовал следующее:

Intent intent = new Intent(this, A.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
startActivity(intent);

Но B и C по-прежнему отображаются, если я использую кнопку «Назад», когда возвращаюсь к занятию A. Как я могу избежать этого?

Ответы:


438

Попробуйте добавить, FLAG_ACTIVITY_NEW_TASKкак описано в документации для FLAG_ACTIVITY_CLEAR_TOP:

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

Итак, ваш код для запуска Aбудет:

Intent intent = new Intent(this, A.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); 
startActivity(intent);
CurrentActivity.this.finish(); // if the activity running has it's own context


// view.getContext().finish() for fragments etc.

28
Спасибо, но я попробовал это. Тем не менее, когда я нажимаю кнопку «Назад» после того, как он снова показывает C. Чего мне не хватает?
Мартин

4
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
dzeikei

8
у меня ничего не получается, однако вызов
метода

10
У меня была та же проблема, что это не работало. Для меня было исправлено вызывать метод finish () после начала нового действия
Арно

20
Я также добавил еще одно ясное намерение: намерение = новое намерение (SingUpActivity.this, LoginActivity.class); intent.setFlags (Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity (намерение); финиш();
Сэм

147
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);

8
При всем уважении к CLEAR_TOPфлагу - эта комбинация является единственной, которая полностью очистила весь стек и сделала новую активность единственной в приложении. Спасибо!
Авиэль Гросс

8
Какая разница между этим и принятым ответом?
Юрий Хеупа

7
Спасибо, разница с принятым ответом состоит в том, что с этим флагом нам не нужно вызывать activity.finish
Pablo Cegarra

1
FLAG_ACTIVITY_CLEAR_TASK отлично работали вместе с NEW_TASK
Шамсул Арефин Саджиб

1
Это должен быть принятый ответ. Большое спасибо.
Доктор медицины датский Ансари

77

Как насчет добавления в файл манифеста для связанной деятельности:

android:noHistory="true"

к определению активности B и C? Они не будут добавлены в backstack. Не уверен, что это то, что вы хотите.


3
Будьте очень осторожны при использовании этого - если вы используете логин с FB или любой подобный тип функциональности
Skynet,

2
@Skynet Почему? Какие проблемы связаны с этим?
Alfie Woodland

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

Это не позволяет деятельности добавить в backstack .... это не правильное решение.
Тарун

Точно я ищу
Масум

63

Это беспокоит меня долгое время. Наконец я решил это, выполнив это:

Во фрагменте используйте:

Intent intent = new Intent(view.getContext(), A.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); 
startActivity(intent);

В Activity используйте (добавьте еще один флаг намерения Intent.FLAG_ACTIVITY_CLEAR_TASKпо сравнению с фрагментом):

Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

1
Если вы используете андроидные аннотации, вы должны добавить: Intent.FLAG_ACTIVITY_CLEAR_TASK
yosafatade

Активность solutioin работала нормально для меня. Хотя я думаю, что с API 16 решение от Даниэля Шулера проще.
PhilippS

Спасибо yosafatade, это было то, что мне не хватало!
Марти Миллер

30
  1. Добавьте android:launchMode="singleTop"к элементу активности в манифесте для действия A
  2. Затем используйте intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) и intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)при запуске действия A

Это означает, что при запуске действия A все задачи поверх него очищаются, так что A находится наверху. Новый задний стек создается с A в корне, и использование singleTopгарантирует, что вы только когда-либо запускаете A один раз (так как A теперь находится на вершине из-за ..._CLEAR_TOP).


3
Да. это то, что я сейчас использую, но это не так. Все еще C появляется, когда я нажимаю кнопку "Назад".
Мартин

Странно, я использовал это в проекте, и он работает нормально ... нажатие назад возвращает меня на домашний экран. Возможно, что-то еще происходит. Не могли бы вы опубликовать свой манифест?
Джозеф Эрл

Я перезапустил эмулятор, и теперь он, кажется, работает так, как вы сказали. Большое спасибо за твою помощь!
Мартин

singleTop не должен иметь ничего общего с очисткой стека.
выход

29

Начиная с API 16 (Jelly Bean), вы можете просто позвонить finishAffinity().

Теперь вы также можете позвонить ActivityCompat.finishAffinity(Activity activity)с библиотекой совместимости.

Обязательно задайте для taskAffinity в манифесте имя пакета, уникальное для этой группы действий.

Для получения дополнительной информации см.
Http://developer.android.com/reference/android/support/v4/app/ActivityCompat.html#finishAffinity%28android.app.Activity%29


Очень удобное и простое решение, если вы уже знакомы с API 16. Работали на меня!
PhilippS

3
напоминание: это будет работать только для действий, в которых используется одно и то же имя задачи
Райан

это работает, только если у вас есть только одно действие в истории.
пришло


11

Если ваше приложение имеет минимальную версию SDK 16, то вы можете использовать finishAffinity ()

Завершите это действие, а также все действия непосредственно под ним в текущей задаче, которые имеют ту же привязку.

Для меня это работа. На экране Top Payment удалите все бэк-стеки,

 @Override
public void onBackPressed() {
         finishAffinity();
        startActivity(new Intent(PaymentDoneActivity.this,Home.class));
    } 

http://developer.android.com/reference/android/app/Activity.html#finishAffinity%28%29



8

Для будущих исследований попробуйте этот код.

Intent intent = new Intent(context, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();

Эти флаги наконец-то сработали для меня. То, что я сделал, я запустил ту же активность, в которой находился, с этими флагами и логическим дополнительным EXIT = true. В onCreate () я проверил параметры запуска для EXIT и вызвал finish (), если было установлено значение true. Это много хлопот, чтобы просто закрыть свое приложение.
Янне Оксанен

8

Используйте finishAffinity (); в задаче C при запуске задачи A для очистки операций обратного стека.


только этот ответ работает для меня. Intent.FLAG_ACTIVITY_CLEAR_TOP и Intent.FLAG_ACTIVITY_NEW_TASK не требуются
Nuttynibbles

7

Используйте этот код для запуска новой Деятельности и закройте или уничтожьте все остальные стеки активности или обратный стек.

Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);

5
Use finishAffinity() to clear all backstack with existing one.

Suppose, Activities A, B and C are in stack, and finishAffinity(); is called in Activity C, 

    - Activity B will be finished / removing from stack.
    - Activity A will be finished / removing from stack.
    - Activity C will finished / removing from stack.

5

Я нашел интересное решение, которое может помочь. Я сделал это в моем onBackPressed()методе.

finishAffinity();
finish();

FinishAffinityудаляет подключение существующего действия к его стеку. А потом финиш поможет вам выйти из этого занятия. Который в итоге выйдет из приложения.


4

Я нашел ответы здесь немного вводящими в заблуждение, потому что код в исходном вопросе, кажется, хорошо работает для меня?

Поскольку A является корневым действием, запуск его с B или C только с FLAG_ACTIVITY_CLEAR_TOP приводит к удалению B и C из заднего стека.


4

В котлине это почти так же, как в Java. Только | символ заменяется на или текст. Итак, это написано как

intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)

3

Я перепробовал все решения, и ни одно из них не работало для меня индивидуально. Мое решение:

Объявить Activity Aкак SingleTopс помощью[android:launchMode="singleTop"] в манифесте Android.

Теперь добавьте следующие флаги при запуске Aиз любого места. Это очистит стек.

Intent in = new Intent(mContext, A.class);
in.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK );
startActivity(in);
finish();

2

Intent.FLAG_ACTIVITY_CLEAR_TOPне будет работать в этом случае. Пожалуйста, используйте(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)

Для более подробной информации, пожалуйста, ознакомьтесь с этой документацией.


2

Это звучит для меня, как будто вы должны начать Activity Cс Activity Bиспользования startActivityForResult(). Когда вы нажимаете кнопку Activity C, вызов setResult(RESULT_OK)и finish()так Activity Cзаканчивается. В Activity B, вы могли бы получить onActivityResult()ответ, также позвонив finish()самому себе, и тогда вас вернут обратно Activity A.


7
Да, но если между А и С есть 42 действия, это будет довольно утомительно. Флаг FLAG_ACTIVITY_CLEAR_TOP должен делать то, что хочет OP.
Гийом Брунери

Это было бы неоптимальным способом достижения того, что хочет OP, и, как сказал @Guillaume, потребовался бы код во всех действиях между корнем и вершиной стека.
Джейк Бэзил

Верно подмечено. Это флаги, о которых я должен узнать, по-видимому.
Максим

1

logout.addFlags (Intent.FLAG_ACTIVITY_CLEAR_TASK); logout.addFlags (Intent.FLAG_ACTIVITY_NEW_TASK);


1

Вы можете использовать этот пример , чтобы позвонить в вашем Activity AизActivity C

Intent loout = new Intent(context, LoginActivity.class); loout.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); context.startActivity(loout);


1

для меня добавление Intent.FLAG_ACTIVITY_CLEAR_TASKрешило проблему

Intent i = new Intent(SettingsActivity.this, StartPage.class);
                i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP  | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(i);
finish();

1

Продвинутый, многоразовый Kotlin:

Вы можете установить флаг напрямую, используя метод установки. В Kotlin orесть замена для битовой Java или |.

intent.flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK

Если вы используете это более одного раза, создайте функцию расширения Intent

fun Intent.clearStack() {
    flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}

Затем вы можете напрямую вызвать эту функцию перед началом

intent.clearStack()

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

fun Intent.clearStack(additionalFlags: Int = 0) {
    flags = additionalFlags or Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}

0

Кроме того FLAG_ACTIVITY_CLEAR_TOP, вы можете попробовать добавить Intent.FLAG_ACTIVITY_SINGLE_TOP:

intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);


Это повлияет только на активность в верхней части стека, а не на его корень.
Джейк Бэйзил

0

Данный код работает правильно. Я пробовал в образце жизненного цикла приложения.

У меня нет B и C в заднем стеке после начала действия A с флагом FLAG_ACTIVITY_CLEAR_TOP


0

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

I tried "FLAG_ACTIVITY_CLEAR_TOP" and "FLAG_ACTIVITY_NEW_TASK"

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


0

Добавьте NO Флаг Истории в намерении.

В упражнении B запустите упражнение C, как показано ниже >>>>>>

Intent intent = new Intent(this, C.class);
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NO_HISTORY); 
startActivity(intent);
finish();


0

Либо добавьте это к вашему Activity BиActivity C

android:noHistory="true"

или Override onBackPressedфункция, чтобы избежать обратного нажатия с return.

@Override
public void onBackPressed() {
   return;
}

0

Используйте метод setFlags (), чтобы очистить заднюю сторону, открыть все действия, закрыть и запустить yourActvity.

Intent intent = new Intent(getApplicationContext(), yourActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.