Android: удалите все предыдущие действия из заднего стека.


119

Когда я нажимаю кнопку « Выход» в своем профиле, я хочу, чтобы пользователь перешел на страницу входа , где ему нужно использовать новые учетные данные.

Следовательно, я использовал этот код:

Intent intent = new Intent(ProfileActivity.this,
        LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

в onButtonClickкнопке выхода.

Но проблема в том, что когда я нажимаю кнопку возврата устройства в Activity Login, я попадаю в ProfileActivity. Я ожидал, что приложение закроется, когда я нажму кнопку возврата устройства в LoginActivity.

Что я делаю не так?

Я также добавил android:launchMode="singleTop"в манифест для моего LoginActivity

Спасибо


@GauravVashisth Я просто следил за этим решением stackoverflow.com/questions/5794506/…
— Archie.bpgc

@ abbas.aniefa Это решение я немного сложнее. Это единственный способ очистить весь задний стек. Поскольку у меня более 30 мероприятий, я должен написать этот код трансляции для всех из них
— Archie.bpgc

попробуйте тогда, stackoverflow.com/questions/10961481/… . Использование Broadcast - лучшее решение.
— abbas.aniefa

другой подход, который вы можете использовать для выхода из системы, после выхода из системы сохраните один флаг в общих настройках и в каждом методе onRestart () действия вы можете проверить значение этой переменной, если для него установлено значение true, вы можете завершить текущее действие. поэтому независимо от того, сколько действий открыто в backgroud. это закончило бы всю вашу деятельность.
— Hiren Dabhi

Ваш исходный код действительно работает для уровня API 11 или выше с настройкой. Вам просто нужно соединить флаги за один вызов: intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);я получил ответ на этот вопрос: stackoverflow.com/questions/3473168/…
— jokeefe

Ответы:


304

Предлагаемое здесь решение сработало для меня:

Ява

Intent i = new Intent(OldActivity.this, NewActivity.class);
// set the new task and clear flags
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);

Котлин

val i = Intent(this, NewActivity::class.java)
// set the new task and clear flags
i.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
startActivity(i)

Однако для этого требуется уровень API> = 11.


Ребят, читайте документацию. FLAG_ACTIVITY_CLEAR_TASKЭто официальный способ получить. Не нужно менять все действия в приложении.
— AlikElzin-kilaka

Это не работает для уведомлений stackoverflow.com/questions/24873131/…
— Сэм

У меня minAPI = 16, поэтому у меня все работает отлично. Однако я заметил, что выполнение представления немного медленнее с API> 21 и плавно с API <21. Кто-нибудь сталкивается с такой же проблемой?
— Red M

1
Это создаст новую задачу для действий
— Рохит

@kgiannakakis Несомненно, решение работает, если у нас есть только одна задача (стек Activity Back), но когда у нас несколько задач (стек Activity), оно не работает. ex- скажем, у меня есть четыре действия для моего приложения A, B, C и D. Предположим, у меня есть два стека активности A-> B-> C (фон) и D-> A-> B (передний план) и If I вызовите действие A из моего текущего стека (D-> A-> B) с фильтром намерений, что вы предложили, что произойдет, очистите мой текущий стек (D-> A-> B) и откройте действие A, и когда я верну его, закройте приложение, но если я нажму кнопку недавнего приложения, я увижу там две задние стопки моего приложения.
— Рахул Парета

31

Вот одно из решений, позволяющих очистить все действия вашего приложения при использовании кнопки выхода.

Каждый раз, когда вы запускаете Activity, запускайте его так:

Intent myIntent = new Intent(getBaseContext(), YourNewActivity.class);
startActivityForResult(myIntent, 0);

Если вы хотите закрыть все приложение, сделайте следующее:

setResult(RESULT_CLOSE_ALL);
finish();

RESULT_CLOSE_ALL - это последняя глобальная переменная с уникальным целым числом, сигнализирующая о том, что вы хотите закрыть все действия.

Затем определите onActivityResult(...)обратный вызов каждого действия, чтобы, когда действие возвращается со значением RESULT_CLOSE_ALL, оно также вызывает finish():

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch(resultCode)
    {
    case RESULT_CLOSE_ALL:
        setResult(RESULT_CLOSE_ALL);
        finish();
    }
    super.onActivityResult(requestCode, resultCode, data);
}

Это вызовет каскадный эффект, который закроет все ваши действия.

Однако это взлом, и он используется startActivityForResultне предназначенным для этого способом.

Возможно, лучший способ сделать это - использовать широковещательные приемники, как показано здесь:

При выходе из системы очистить стек истории активности, не позволяя кнопке «назад» открывать Активы только для входа в систему.

См. Также эти темы для других методов:

Android: очистить задний стек

Завершить все предыдущие действия


4
Возможно ли это, когда у вас около 30 заданий по истории ??
— Ракеш Гондалия

4
должно быть. Но если у вас есть 30 занятий в истории, возможно, вам стоит подумать об изменении дизайна. 30 кажется многовато, и Android может убить их сам.
— Anup Cowkur

1
Это кажется плохим способом сделать это. Вопрос ответа @RakeshGondaliya кажется законным. 30 может быть просто числом, представляющим «большое» количество занятий. Этот ответ выглядит лучше: stackoverflow.com/a/3008684/243709
— Аман Алам,

Это отличный ответ. Вы также можете использовать библиотеку EventBus для отправки событий своим действиям в backstack. github.com/greenrobot/EventBus
— Стэн

Лучше использовать простой флаг «Intent.FLAG_ACTIVITY_CLEAR_TOP» с намерением
— Навин Рао,

18

Чтобы полностью очистить стек действий, вы хотите создать новый стек задач с помощью TaskStackBuilder, например:

Intent loginIntent = LoginActivity.getIntent(context);
TaskStackBuilder.create(context).addNextIntentWithParentStack(loginIntent).startActivities();

Это не только создаст новый чистый стек задач, но и обеспечит правильное функционирование кнопки «вверх», если ваша LoginActivity имеет родительскую активность.


1
Это лучший способ сделать это.
— Пол Берк,

FLAG_ACTIVITY_NEW_TASKили finishAffinity()не работал у меня. Только этот ответ решил цель.
— TM

Если я выхожу из приложения с помощью кнопки «Назад» и возвращаюсь с помощью значка приложения, оно открывается в действии, которое я назвал этим методом. Так что у меня не работает.
— Tgo1014

17

finishAffinity()добавлено в API 16. Используется ActivityCompat.finishAffinity()в предыдущих версиях. Когда вы запустите любое действие с использованием намерения и завершите текущее действие. Теперь используйте ActivityCompat.finishAffinity()вместо этого finish(). он завершит всю сложенную активность ниже текущей. Он отлично работает для меня.


3
Это на самом делеActivityCompat.finishAffinity()
— Берга

finishAffinity()также завершает текущее действие со всеми действиями, присутствующими в заднем стеке того же соответствия.
— Нирадж Севани 02

10

Что сработало для меня

Intent intent = new Intent(getApplicationContext(), HomeActivity.class);
ComponentName cn = intent.getComponent();
Intent mainIntent = IntentCompat.makeRestartActivityTask(cn);
startActivity(mainIntent);

5

Одно из возможных решений, которое я могу вам предложить, - это добавить android:launchMode="singleTop"в манифест для моей ProfileActivity . и при нажатии кнопки выхода вы можете выйти из системы, снова запустив LoginActivity. при выходе из системы вы можете вызвать это.

Intent in = new Intent(Profile.this,Login.class);
                in.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(in);
                finish();

Я сделал это, вот что произошло: когда я нажимаю кнопку «Назад», я попадаю в Activty, откуда я пришел в
— ProfileActivity

Это может произойти из-за того, что u перешел в ProfileActivity, вызвав новое намерение, а не вызвав finish (); Как вы попадаете в ProfileActivity из других видов деятельности, кроме LoginActivty?
— Android

Я пересекаю тот же вопрос. Я думаю, что это не сработает, если намерение входа в систему было уничтожено системой, скажем, из-за отсутствия памяти.
— user1914692 08

5

Для API 11+ вы можете использовать Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASKэто так:

Intent intent = new Intent(this, MyActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);

Он полностью очистит все предыдущие действия и начнет новую деятельность.


4

Вы можете попробовать finishAffinity(), он закрывает все текущие действия и работает на Android 4.1 и выше.


1
finishAffinity () добавлено в API 16. Используйте ActivityCompat.finishAffinity () в предыдущей версии. У меня работает нормально.
— Анураг Шривастава

2

Я тоже столкнулся с той же проблемой ..

в активности входа в систему, что я делаю.

    Intent myIntent = new Intent(MainActivity.this, ActivityLoggedIn.class);
    finish();
    MainActivity.this.startActivity(myIntent);  

при выходе

   Intent myIntent = new Intent(ActivityLoggedIn.this, MainActivity.class);
   finish();
   ActivityLoggedIn.this.startActivity(myIntent);

Это работает хорошо, но когда я нахожусь в ActivityLoggedIn, свертываю приложение и нажимаю значок кнопки запуска на панели приложений, MainActivity запускается снова: - / я использую флаг

android:LaunchMode:singleTask 

для MainActivity.


2

Используйте следующее для activity

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

удалить CLEAR_TASK флаг для использования фрагмента.

Я надеюсь, что это может пригодиться некоторым людям.


1

Просто держи

Intent intent = new Intent(ProfileActivity.this,
    LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
startActivity(intent);

4
Это не работает. Я все еще могу перейти в ProfileActivity, используя кнопку «Назад»
— Archie.bpgc

1

Ни один из флагов намерений у меня не работал, но вот как я это исправил:

Когда пользователь выходит из одного действия, мне приходилось транслировать сообщение из этого действия, затем получать его в действиях, которые я хотел закрыть, после чего я вызываю finish (); и это работает очень хорошо.


1

Попробуйте, это сработает:

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

На уровне API 11 или выше используйте FLAG_ACTIVITY_CLEAR_TASKи FLAG_ACTIVITY_NEW_TASKотметьте намерение, чтобы очистить весь стек активности.

Intent i = new Intent(OldActivity.this, NewActivity.class);
// set the new task and clear flags
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |  Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(i);

0

Использовать это

Intent i1=new Intent(getApplicationContext(),StartUp_Page.class);
i1.setAction(Intent.ACTION_MAIN);
i1.addCategory(Intent.CATEGORY_HOME);
i1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
i1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i1);
finish();

вы знали setFlags и addFlags?
— GvSharma


0

Продвинутый, повторно используемый Котлин:

Вы можете установить флаг напрямую, используя метод setter. В Kotlin orесть замена Java на побитовый или |.

intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK

Если вы планируете использовать это регулярно, создайте функцию расширения Intent

fun Intent.clearStack() {
    flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}

Затем вы можете напрямую вызвать эту функцию перед запуском намерения

intent.clearStack()

Если вам нужна возможность добавления дополнительных флагов в других ситуациях, добавьте необязательный параметр в функцию расширения.

fun Intent.clearStack(additionalFlags: Int = 0) {
    flags = additionalFlags or Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.