Как вы используете Intent.FLAG_ACTIVITY_CLEAR_TOP для очистки стека действий?

85

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

// 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, но затем кнопка возврата снова вернула меня в браузер!

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

Piusvelte
источник

Ответы:

72

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

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

ScouseChris
источник
52
На самом деле ... так Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOPи сделаю.
Дерк-
Посмотрите решение Steel_fedex на его примере.
Darpan
2
так где, черт возьми, решение Steel_fedex ?!
ChangWon Jeong Juicycool
112

Я начал Activity A-> B-> C-> D. Когда кнопка возврата нажата в Activity D, я хочу перейти к Activity A. Поскольку A - моя отправная точка и, следовательно, уже в стеке, все действия в верхней части A очищаются, и вы не можете вернуться к любому другому Activity из 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);
}       
Джеспер Бишофф-Йенсен
источник
4
Это решение закрывает всю посредническую деятельность; но также перезапуск RootActivity. Вы можете проверить решение @ Steel_Fedex ниже. Он делает то же самое, но не перезапускает RootActivity.
Darpan
Это лучшее решение для моего случая. Я действительно хочу, чтобы корневое действие запустилось снова
Таш Пемхива
24

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

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

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

Федир Цапана
источник
Я проверил, Решение Битстера не работает. Пока это решение работало. RootActivity не перезапустился.
Darpan
Подбирайте слова более мудро. Решение Bitestar действительно работает!
Jesper Bischoff-Jensen
singleTask работает для меня, поэтому Activity не будет воссоздавать и обрабатывать событие в onNewIntent.
Jishi Chen
11

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

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

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


Итак, Либо,
1 . Измените действие launchModeActivity A на что-то другое из стандартного (например, singleTaskили что-то в этом роде). Тогда ваш флаг FLAG_ACTIVITY_CLEAR_TOPне перезапустит действие A.

или же,

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>
Ахмад Агазаде
источник
Впервые вижу этот флаг, но в моем случае он сработал, спасибо
власентий
3

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

I tried "FLAG_ACTIVITY_CLEAR_TOP" and "FLAG_ACTIVITY_NEW_TASK"

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

Своп-IOS-Android
источник
2

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

Возможно, его сбивает с толку то, что A - singleTop, тогда как должно быть singleTask. Если A - singleTop, а 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. Итак, чтобы действительно проверить это, обязательно выйдите из браузера перед запуском приложения.

Кевин
источник
1

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

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

Прочтите это и флаги намерений здесь

100раб
источник
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
B должен получить ответное намерение из браузера. Я попытался изменить режим запуска на singleTask, и он все еще работает, но зацикливание кнопки возврата все еще происходит.
piusvelte
Я думаю, что это не сработало, потому что вы использовали здесь FLAG_ACTIVITY_NEW_TASK. Лучше используйте только FLAG_ACTIVITY_CLEAR_TOP и избегайте использования ни singleTask, ни singleInstance
100rabh
1
Я думаю, что это должно быть рабочее решение, если вы добавите, Intent.FLAG_ACTIVITY_SINGLE_TOPчтобы предотвратить воссоздание
yonojoy
1

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

ja_chu
источник