Очистите весь стек истории и запустите новое действие на 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 с помощью командной строки.