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
Возможный дубликат Android: очистите задний стек
Мехди Дехгани

Ответы:

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);
whlk
источник
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

Maxp
источник
2

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

intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.ClearTask);
БИШИМО Audace
источник
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()
Gibolt
источник