Як ви використовуєте Intent.FLAG_ACTIVITY_CLEAR_TOP для очищення стеку активності?


84

Я прочитав кілька постів про використання цього, але, мабуть, щось не вистачає, оскільки це не працює для мене. У моїй діяльності A у маніфесті є launchmode = "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, Browser, B

Я очікую, що цей код змінить стек на ... A ... так, що натискання назад ще раз поверне користувача назад на головний екран.

Натомість він, здається, змінює стек на ... A, B, Browser, B, A ... так, ніби цих прапорів там немає.

Я спробував викликати finish () у дії B після startActivity, але потім кнопка "Назад" знову повертає мене до браузера!

Чого мені не вистачає? Дякую!

Відповіді:


72

@bitestar має правильне рішення, але є ще один крок:

Це було заховано в документах, однак ви повинні змінити launchModeйого Activityна будь-що інше, ніж standard. В іншому випадку він буде знищений і відтворений, замість того, щоб скинути його на початок.


51
Власне ... Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOPзроблю саме це.
Дерк-Січ

Перевірте рішення Steel_fedex на прикладі.
Дарпан

2
так де, чорт візьми, рішення Steel_fedex ?!
ChangWon Jeong Juicycool

112

Я розпочав діяльність A-> B-> C-> D. Коли натиснута кнопка "Назад" на Діянні DI, потрібно перейти до Діяльності А. Оскільки А є моєю відправною точкою, і тому вже у стеку всі дії у верхній частині А очищаються, і Ви не можете повернутися до будь-якої іншої Діяльності з А .

Це насправді працює в моєму коді:

@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);
}       

4
Це рішення закриває всю посередницьку діяльність; але також, перезапуск RootActivity. Ви можете перевірити рішення @ Steel_Fedex нижче. Він робить те саме, але не перезапускає RootActivity.
Дарпан

Це найкраще рішення для мого випадку. Я насправді хочу, щоб коренева активність запускалася знову
Таш Пемхіва,

24

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

і launchMode = "singleTask"в маніфесті для запущеної діяльності.

Здається, це працює, як мені потрібно - діяльність не перезапускається, а всі інші дії закриті.


Я перевірив, рішення Bitster не працює. Поки це рішення працювало. RootActivity не перезапустився.
Дарпан

Підбирайте слова більш розумно. Рішення Bitestar насправді працює!
Jesper Bischoff-Jensen

singleTask працює для мене, тому Activity не буде відтворювати та обробляти події в onNewIntent.
Jishi Chen

11

Хоча на це питання вже є достатньо відповідей, я думав, хтось хотів би знати, чому цей прапор працює у такий своєрідний спосіб, ось що я знайшов у документації Android

Наразі запущений екземпляр дії B у наведеному вище прикладі або отримає новий намір, який ви починаєте тут, у своєму методі onNewIntent (), або сам буде закінчений і перезапущений з новим наміром.

Якщо він оголосив свій режим запуску "багаторазовим" (за замовчуванням), і ви не встановили FLAG_ACTIVITY_SINGLE_TOP з однаковим наміром, тоді він буде закінчений і створений заново; для всіх інших режимів запуску або якщо встановлено FLAG_ACTIVITY_SINGLE_TOP, тоді цей намір буде доставлений до поточного екземпляра onNewIntent ().


Отже, будь-який,
1 . Змінюйте launchModeДіяльність А на щось інше зі стандартного (тобто, singleTaskщось інше). Тоді ваш прапор FLAG_ACTIVITY_CLEAR_TOPне перезапустить вашу активність А.

або,

2 . Використовуйте Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOPяк свій прапор. Тоді це буде працювати так, як ти бажаєш.


8

Для вирішення проблеми я використовую три прапори:

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

4

Додайте android: noHistory = "true" у файл маніфесту.

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

</manifest>

Вперше бачу цей прапор, але він спрацював для моєї справи, дякую
vlasentiy

3

я зателефонував activity_name.this.finish()після початку нового наміру, і це в мене спрацювало.

I tried "FLAG_ACTIVITY_CLEAR_TOP" and "FLAG_ACTIVITY_NEW_TASK"

Але це не спрацює для мене ... Я не пропоную це рішення для використання, але якщо прапор встановлення не буде працювати для вас, ви можете спробувати це ... Але все-таки я рекомендую не використовувати


2

Я знаю, що вже прийнята відповідь, але я не бачу, як це працює для ОП, оскільки не думаю, що FLAG_ACTIVITY_CLEAR_TOP є значущим у його конкретному випадку. Цей прапор актуальний лише для діяльності, що виконує одне і те ж завдання . На основі його опису кожна діяльність має своє власне завдання : A, B та браузер.

Щось, що може його відкинути, це те, що A є singleTop, коли це має бути singleTask. Якщо A є singleTop, а B починає A, тоді буде створено нове A, оскільки A не є завданням B. З документації для singleTop:

"Якщо екземпляр діяльності вже існує вгорі поточного завдання , система перенаправляє намір до цього екземпляра ..."

Оскільки B починає A, поточним завданням є завдання B, яке призначене для єдиної інстанції, і тому не може включати A. Використовуйте singleTask для досягнення бажаного результату там, оскільки тоді система знайде завдання, яке має A, і виведе це завдання на перший план.

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


1

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

Ну, я рекомендую вам прочитати, що робить кожен прапор, перш ніж працювати з ними

Прочитайте це та прапори намірів тут


1
Я прочитав прапор, і це звучало як те, що мені потрібно. Незважаючи на це, видалення FLAG_ACTIVITY_NEW_TASK не впливає на результат. Це все ще нескінченний цикл кнопок назад ... A-> B, назад до A, назад до B, назад до A ...
piusvelte

Ви впевнені, чому ви використовуєте B як singleInstance? Діяльність AA "singleInstance" діє так, ніби FLAG_ACTIVITY_NEW_TASK був у намірі. Перевірте developer.android.com/guide/topics/fundamentals.html
100rabh

Б повинен отримати передзвонений намір від браузера. Я спробував змінити режим запуску на singleTask, і це все ще працює, але циклічне повернення кнопки все одно відбувається.
piusvelte

я думаю, це не спрацювало, бо ви використовували там FLAG_ACTIVITY_NEW_TASK. Краще використовуйте лише FLAG_ACTIVITY_CLEAR_TOP і уникайте використання ані singleTask, ані
singleInstance

1
Я думаю, що це має бути робочим рішенням, якщо ви додасте, Intent.FLAG_ACTIVITY_SINGLE_TOPщоб запобігти відтворенню
yonojoy

1

Спочатку у мене також були проблеми з приводу роботи FLAG_ACTIVITY_CLEAR_TOP. Зрештою я змусив його працювати, використовуючи його значення (0x04000000). Отже, схоже, є проблема Eclipse / компілятора. Але, на жаль, діяльність, що вижила, перезапускається, що я не хочу. Отож, схоже, немає простого рішення.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.