Android: Очистить стек активности
У меня есть несколько действий в моей заявке. и поток очень сложный. Когда я нажимаю на кнопку "Выйти", происходит переход к экрану входа в систему, после чего пользователь может выйти с помощью кнопки "Отмена" (вызов 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);
9 ответов
Большинство из вас не правы. Если вы хотите закрыть существующий стек активности независимо от того, что там находится, и создать новый корень, правильный набор флагов будет следующим:
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
public static final int FLAG_ACTIVITY_CLEAR_TASK
Добавлено в API уровень 11Если установлено в намерении, переданном
Context.startActivity()
этот флаг приведет к тому, что любая существующая задача, которая будет связана с действием, будет очищена перед началом действия. Таким образом, действие становится новым корнем в противном случае пустой задачи, и все старые действия завершаются. Это может быть использовано только в сочетании сFLAG_ACTIVITY_NEW_TASK
,
Когда вы звоните startActivity
на последнем мероприятии вы всегда можете использовать
Intent.FLAG_ACTIVITY_CLEAR_TOP
как флаг на это намерение.
Подробнее о флаге читайте здесь.
Вот простой вспомогательный метод для запуска нового действия в качестве нового основного действия, которое работает с уровня 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);
Очистить активность 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);
Готово
Это решение отлично работает:
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.
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();
В моем случае, LoginActivity также было закрыто. В следствии,
Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK
не помогло.
Однако настройка
Intent.FLAG_ACTIVITY_NEW_TASK
помог мне.
Использование Kotlin:
Вы можете установить флаг напрямую, используя метод setter. В Котлине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()
Для разработчиков Xamarin вы можете использовать:
intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.ClearTask);
Я отметил, что вы просили решение, которое не полагается на 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()
, После этого другие соответствующие действия, которые возобновляются автоматически, также будут завершены.
Намерение намерения = новое намерение (LoginActivity.this,MainActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); startActivity(намерение); финиш();