Android: очистить стек активности


132

В моем приложении есть несколько действий. и поток очень сложный. Когда я нажимаю кнопку выхода, приложение переходит на экран входа в систему, и оттуда пользователь может выйти, нажав кнопку отмены (вызов system.exit(0))

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

validateuser logoutuser = new validateuser();
logoutuser.logOut();
Intent loginscreen = new Intent(homepage.this, Login2.class);
(homepage.this).finish();
loginscreen.setFlags( Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(loginscreen);

1
проверьте эту ссылку ... stackoverflow.com/questions/5139686/exit-an-android-app/…
— xydev

Ответы:


339

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

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

Из документа :

public static final int FLAG_ACTIVITY_CLEAR_TASK
Добавлено в API уровня 11

Если установлен в Intent, переданном в Context.startActivity(), этот флаг приведет к тому, что любая существующая задача, которая будет связана с действием, будет очищена перед запуском действия. То есть действие становится новым корнем пустой задачи, и все старые действия завершаются. Его можно использовать только вместе с FLAG_ACTIVITY_NEW_TASK.


Работал отлично. Спасибо. Странно не выдавало ошибки с minSDK = 9.
— Mahm00d

Честно говоря, я никогда не использовал эту функциональность, воскрешал после сбоя и т. Д., А сосредоточился на исправлении проблем, вызвавших сбой)
— Циничный Бандера

Та же функциональность также предоставляется IntentCompat.makeRestartActivityTaskиз библиотеки поддержки.
— sealskej 07

Добавление только этих двух флагов оставляет трек стека активности позади (начинается поверх предыдущего), затем добавляется Intent.FLAG_ACTIVITY_CLEAR_TOP, который просто перезапускает приложение, а затем полностью закрывается. Я не добавлял никаких флагов к действиям явно. В чем может быть проблема?
— Фарид

1
Одно из лучших начинаний: «Большинство из вас ошибаются».
— ниббана

31

Когда вы вызываете startActivityпоследнее действие, вы всегда можете использовать

Intent.FLAG_ACTIVITY_CLEAR_TOP

как флаг этого намерения.

Подробнее о флаге здесь .


это тоже не помогает. Я просто вызываю действие, которое не заканчивается на finish (); :(
— Джей Маю

Я предполагаю, что FLAG_ACTIVITY_CLEAR_TOP очищает действия вверху. Моя проблема в активности внизу :(
— Джей Маю

Думаю, это зависит от того, как на самом деле идет поток. Вы должны узнать об этом больше здесь: developer.android.com/reference/android/content/… и developer.android.com/guide/topics/fundamentals/…
— Дэвид Олссон

7
Спасибо за правильные ресурсы. ошибка, которую я сделал, заключалась в закрытии действия входа в систему. Я не должен закрывать это. Когда действие загружается первым. поэтому, когда я вызываю его обратно, используя флаг Clear_top, активность входа очищает все действия наверху. поскольку вход в систему является первым действием входа, он очищает все действия, начатые после. так что бинго это сработало :)
— Джей Маю

13
Из документации, FLAG_ACTIVITY_CLEAR_TOP очищает стек, только если конкретное действие «уже выполняется в текущей задаче»
— AlikElzin-kilaka

16

Вот простой вспомогательный метод для запуска нового действия в качестве нового основного действия, которое работает с уровня API 4 до текущей версии 17:

static void startNewMainActivity(Activity currentActivity, Class<? extends Activity> newTopActivityClass) {
    Intent intent = new Intent(currentActivity, newTopActivityClass);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
        intent.addFlags(0x8000); // equal to Intent.FLAG_ACTIVITY_CLEAR_TASK which is only available from API level 11
    currentActivity.startActivity(intent);
}

назовите это так из своей текущей деятельности:

startNewMainActivity(this, MainActivity.class);

1
Не могли бы вы просто использовать intent.addFlags (0x8000); и упростить это?
— Davor

Поскольку этот флаг был впервые представлен в Honeycomb, я понятия не имею, какое значение он может иметь в более ранних версиях. Итак, это были мои меры предосторожности. Но я думаю, что удалить условный знак проблем не должно.
— whlk 06

1
вы хотите добавить этот флаг, когда уровень API <11, тогда вам нужно сделать, Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMBиначе intent.addFlags(0x8000);никогда не будет добавлено
— Соломенная Шляпа

Я заставляю пользователя выполнять множество действий одно за другим с помощью намерений. Нужно ли мне что-то делать, чтобы приложение не вылетало из-за слишком большого количества действий в стеке? Спасибо!
— Ручир Барония

9

Очистите Activity Backstate с помощью кода ниже:

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

Готово


Я заставляю пользователя выполнять множество действий одно за другим с помощью намерений. Нужно ли мне что-то делать, чтобы приложение не вылетало из-за слишком большого количества действий в стеке? Спасибо!
— Ручир Барония

@RuchirBaronia, если вы пойдете A -> B -> C -> D -> E -> F -> G -> H, теперь H -> Я напишу мой код, чем я буду последним действием, после чего вы нажмете кнопку Назад приложение будет закрыто, потому что приложение не имеет предыстории, надеюсь, это вам поможет.
— Hiren Patel

Но нужно ли мне это делать? Что произойдет, если я никогда не очищу стек активности?
— Ручир Барония,

@RuchirBaronia, Backpress: H -> G -> F -> E -> D -> C -> B -> A
— Hiren Patel

Но некоторое время он показывает белый экран при вызове новой активности. Как решить это?
— Сагар

4

В моем случае LoginActivity тоже был закрыт. В следствии,

Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK

не помогло.

Однако установка

Intent.FLAG_ACTIVITY_NEW_TASK

помог мне.


Я заставляю пользователя выполнять множество действий одно за другим с помощью намерений. Нужно ли мне что-то делать, чтобы приложение не вылетало из-за слишком большого количества действий в стеке? Спасибо!
— Ручир Барония,

3
Intent intent = new Intent(LoginActivity.this, Home.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);  //It is use to finish current activity
startActivity(intent);
this.finish();

1
почему вы используете и то, this.finish()и другое, а setFlags()также для очистки текущей активности?
— Сагар

3

Я заметил, что вы просили решение, которое не зависит от finish() , но мне интересно, может ли это помочь.

Я отслеживал, поднимается ли флаг выхода с помощью статической переменной класса, которая сохраняется в течение всего срока службы приложения. В каждой соответствующей деятельности onResume()используйте

@Override
public void onResume() {
    super.onResume();
    if (ExitHelper.isExitFlagRaised) {
        this.finish();
    }
}

Класс ExitHelper

public class ExitHelper {
    public static boolean isExitFlagRaised = false;
}

Скажем, в mainActivity пользователь нажимает кнопку для выхода - вы можете установить ExitHelper.isExitFlagRaised = true;и затем finish(). После этого другие соответствующие действия, которые возобновляются автоматически, также будут завершены.


что произойдет, если я использую код в MainActivity onresume (), а затем вернусь к mainactivity из 2-го действия onbackpress
— Mithu

3

Это решение работает нормально:

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

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

public class BaseActivity extends AppCompatActivity {

    private static final String ACTION_FINISH = "action_finish";

    private BroadcastReceiver finisBroadcastReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        registerReceiver(finisBroadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                finish();
            }
        }, new IntentFilter(ACTION_FINISH));
    }

    public void clearBackStack() {
        sendBroadcast(new Intent(ACTION_FINISH));
    }

    @Override
    protected void onDestroy() {
        unregisterReceiver(finisBroadcastReceiver);
        super.onDestroy();
    }
}

Как это использовать:

public class ActivityA extends BaseActivity {

    // Click any button
    public void startActivityB() {
        startActivity(new Intent(this, ActivityB.class));
        clearBackStack();
    }
}

Недостаток: все действия, которые должны быть закрыты в стеке, должны расширять BaseActivity


2

Для разработчиков Xamarin вы можете использовать:

intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.ClearTask);

1

Использование Kotlin:

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

intent.flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK

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

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

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

intent.clearStack()
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.