Очистить весь стек истории и начать новое действие на Android - PullRequest
305 голосов
/ 13 августа 2010

Можно ли запустить действие в стеке, очистив всю историю до него?

Ситуация

У меня есть стек действий, который либо идет A-> B-> C или B-> C (экран A выбирает токен пользователя, но у многих пользователей только один токен).

На экране C пользователь может выполнить действие, которое делает экран B недействительным, поэтому приложение хочет перенести их на экран A, независимо от того, находится ли он уже в стеке.Тогда экран А должен быть единственным элементом в стеке в моем приложении.

Примечания

Есть много других подобных вопросов, но я не нашел ничего, что отвечало быэто точный вопрос.Я попытался вызвать getParent().finish() - это всегда приводит к исключению нулевого указателя.FLAG_ACTIVITY_CLEAR_TOP работает, только если действие уже находится в стеке.

Ответы [ 12 ]

608 голосов
/ 17 марта 2011

На уровне API 11 новый флаг намерений был добавлен только для этого: Intent.FLAG_ACTIVITY_CLEAR_TASK

Просто чтобы уточнить, используйте это:

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

К сожалению, для API lvl <= 10 я еще не нашел чистого решения для этого. Решение <a href="/3605639/ochistit-ves-stek-istorii-i-nachat-novoe-deistvie-na-android#3605645"> "DontHackAndroidLikeThis" действительно является чистой взломом. Вы не должны этого делать. :)

Изменить: Согласно комментарию @ Бена Пирсона , для API <= 10 теперь можно использовать класс <a href="http://developer.android.com/reference/android/support/v4/content/IntentCompat.html#FLAG_ACTIVITY_CLEAR_TASK" rel="noreferrer"> IntentCompat для того же самого. Можно использовать флаг IntentCompat.FLAG_ACTIVITY_CLEAR_TASK, чтобы очистить задачу. Таким образом, вы также можете поддерживать предварительный уровень API 11.

46 голосов
/ 03 мая 2013

Случай 1: только два вида деятельности A и B:

Здесь поток операций - это A-> B.. Нажав кнопку B, мы должны закрыть приложение, а затем при запуске действия B из A просто вызвать метод finish (), чтобы Android не смог сохранить действие A в Backstack.eg для активность A - Loding / Splash экран приложения.

Intent newIntent = new Intent(A.this, B.class);
startActivity(newIntent);
finish();

Случай 2: Более двух видов деятельности:

Если есть такой поток, как A-> B-> C-> D-> B и при нажатии кнопки «Назад» в Деятельности B при переходе из Деятельности D. В этом случае мы должны использовать.

Intent newIntent = new Intent(D.this,B.class);
newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(newIntent);

Здесь действие B будет запускаться из обратного стека, а не из нового экземпляра из-за Intent.FLAG_ACTIVITY_CLEAR_TOP и Intent.FLAG_ACTIVITY_NEW_TASK очищает стек и делает его верхним. Так что, когда мы нажимаем кнопку назад, все приложение будет завершено. 1015 *

33 голосов
/ 14 сентября 2016

с более новой версией Android> = использование API 16 finishAffinity()

подход подходит для> = API 16.

Intent mIntent = new Intent(mContext,MainActivity.class);
finishAffinity();
startActivity(mIntent);
  • Это то же самое, что начинать новое действие и очищать весь стек.
  • ИЛИ Перезапустите MainActivity / FirstActivity.
21 голосов
/ 18 октября 2013

Я тоже потратил на это несколько часов ... и согласен с тем, что FLAG_ACTIVITY_CLEAR_TOP звучит так, как вам бы хотелось: очистить весь стек, кроме запускаемого действия, чтобы кнопка «Назад» выходила из приложения.Тем не менее, как отметил Майк Репасс, FLAG_ACTIVITY_CLEAR_TOP работает только тогда, когда запускаемое вами действие уже находится в стеке;когда действия отсутствуют, флаг ничего не делает.

Что делать?Поместите запускаемое действие в стек с помощью FLAG_ACTIVITY_NEW_TASK, что делает это действие началом новой задачи в стеке истории.Затем добавьте флаг FLAG_ACTIVITY_CLEAR_TOP.

Теперь, когда FLAG_ACTIVITY_CLEAR_TOP перейдет к поиску новой активности в стеке, она будет там и будет поднята до того, как все остальное будет очищено.

Вот мой выход из системыфункция;параметр View - это кнопка, к которой присоединена функция.

public void onLogoutClick(final View view) {
    Intent i = new Intent(this, Splash.class);
    i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    startActivity(i);
    finish();
}
12 голосов
/ 13 августа 2010

Вы не должны менять стек. Кнопка возврата Android должна работать как в веб-браузере.

Я могу придумать, как это сделать, но это довольно круто.

  • Сделайте свою деятельность singleTask, добавив ее в AndroidManifest Пример:

    <activity android:name=".activities.A"
              android:label="@string/A_title"
              android:launchMode="singleTask"/>
    
    <activity android:name=".activities.B"
              android:label="@string/B_title"
              android:launchMode="singleTask"/>
    
  • Расширение Application, которое будет содержать логику того, куда идти.

Пример:

public class DontHackAndroidLikeThis extends Application {

  private Stack<Activity> classes = new Stack<Activity>();

  public Activity getBackActivity() {
    return classes.pop();
  }

  public void addBackActivity(Activity activity) {
    classes.push(activity);
  }
}

От А до Б:

DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication();
app.addBackActivity(A.class); 
startActivity(this, B.class);

От B до C:

DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication();
app.addBackActivity(B.class); 
startActivity(this, C.class);

В С:

If ( shouldNotGoBackToB() ) {
  DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication();
  app.pop();
}

и перетащите кнопку возврата на pop() из стека.

Еще раз, вы не должны этого делать:)

11 голосов
/ 04 апреля 2012

Сразу после начала нового действия, используя startActivity, убедитесь, что вы набрали finish(), чтобы текущее действие не укладывалось за новым.

4 голосов
/ 13 июня 2017

Попробуйте это:

Intent logout_intent = new Intent(DashboardActivity.this, LoginActivity.class);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(logout_intent);
finish();
1 голос
/ 14 ноября 2018

Попробуйте код ниже,

Intent intent = new Intent(ManageProfileActivity.this, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|
                Intent.FLAG_ACTIVITY_CLEAR_TASK| 
                Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
1 голос
/ 13 декабря 2017
Intent i = new Intent(MainPoliticalLogin.this, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);
0 голосов
/ 24 мая 2019

Для меня нет из вышеперечисленных методов не работает.

Просто сделайте это, чтобы очистить все предыдущие действия :

finishAffinity() // if you are in fragment use activity.finishAffinity()
Intent intent = new Intent(this, DestActivity.class); // with all flags you want
startActivity(intent)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...