Очистите весь стек истории и запустите новое действие на Android

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

Ситуация

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

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

Примечания

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

Ответ 1

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

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

Java

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


Котлин

intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK


К сожалению, для API lvl & lt; = 10 я еще не нашел чистого решения для этого. Решение "DontHackAndroidLikeThis" действительно является чистой взломом. Вы не должны этого делать. :)

Изменить: Согласно комментарию @Бена Пирсона, для API & lt; = 10 теперь можно использовать класс IntentCompat для того же самого. Для очистки задачи можно использовать флаг IntentCompat.FLAG_ACTIVITY_CLEAR_TASK. Таким образом, вы также можете поддерживать предварительный уровень API 11.

Ответ 2

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

Здесь поток активности A- > B. При щелчке по кнопке от B нам нужно закрыть приложение, а затем при запуске Activity B из A just call finish() это предотвратит сохранение андроидом активности 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 запускается из backstack, а не из нового экземпляра из-за Intent.FLAG_ACTIVITY_CLEAR_TOP и Intent.FLAG_ACTIVITY_NEW_TASK очищает стек и делает его верхним. Поэтому, когда мы нажимаем кнопку "Назад", вся заявка будет завершена.

Ответ 3

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

Подход

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

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

Ответ 4

Я тоже потратил несколько часов на это... и согласен с тем, что 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();
}

Ответ 5

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

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

  • Сделайте свои действия 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);
  }
}

От A до B:

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

В C:

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

и откройте обратную кнопку pop() из стека.

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

Ответ 6

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

Ответ 7

Попробуйте следующее:

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();

Ответ 8

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

Ответ 9

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

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

Ответ 10

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

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

finishAffinity() // if you are in fragment use activity.finishAffinity()
Intent intent = new Intent(this, DestActivity.class); // with all flags you want
startActivity(intent)

Ответ 11

Я нашел слишком простой хак, просто добавьте новый элемент в AndroidManifest как: -

<activity android:name=".activityName"
          android:label="@string/app_name"
          android:noHistory="true"/>

android:noHistory очистит вашу нежелательную активность от Stack.

Ответ 12

Иногда ваш эмулятор android может не подключиться к инструменту DDL eclipse и попросить запустить adb вручную. В этом случае вы можете запустить или остановить adb с помощью командной строки.