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注销”按钮的中。

但是问题是,当我单击登录活动上的设备后退按钮时,它将带我到ProfileActivity。我期望当我在LoginActivity上按设备后退按钮时,应用程序应该关闭。

我究竟做错了什么?

我还android:launchMode="singleTop"为我的LoginActivity添加了清单

谢谢


@GauravVashisth我只是下面的这个解决方案stackoverflow.com/questions/5794506/...
Archie.bpgc

@ abbas.aniefa这个解决方案我有点复杂。这是清除所有后备堆栈的唯一方法。因为我有30多个活动,所以我应该为所有人编写此广播代码
Archie.bpgc 2012年

然后尝试一下stackoverflow.com/questions/10961481/…。使用广播是一个更好的解决方案。
abbas.aniefa 2012年

可以用于注销的另一种方法,注销后将一个标志存储在sharedpreferences中,并且在活动的每个onRestart()方法中都可以检查此变量值(如果将其设置为true),则可以完成当前活动。因此,无论背景中打开了多少活动。这将完成您的所有活动。
Hiren Dabhi 2012年

原始代码实际上需要经过一些调整才能用于API级别11或更高。你只需把国旗在一个单一的电话:intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);我是从这个问题的答案:stackoverflow.com/questions/3473168/...
jokeefe

Answers:


301

这里提出的解决方案为我工作:

爪哇

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时视图执行流畅。有人遇到同样的问题吗?
红色M

1
这将为活动创建一个新任务
Rohit19年

@kgiannakakis毫无疑问,如果只有一个任务(活动返回堆栈),则解决方案将起作用,但是当我们有多个任务(活动堆栈)时,该方案将无法正常工作。假设我有四个针对应用程序A,B,C和D的活动。假设我有两个活动反向堆栈A-> B-> C(背景)和D-> A-> B(前景),如果我使用意图过滤器从我当前的堆栈(D-> A-> B)调用活动A,您建议会发生什么,清除当前堆栈(D-> A-> B)并打开活动A,然后按回车键关闭应用程序,但是如果我按了最近使用的应用程序按钮,则可以在其中看到我的应用程序的两个反向堆栈。
Rahul Pareta

31

这是一种使用注销按钮清除应用程序所有活动的解决方案。

每次启动活动时,都应像这样启动它:

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);
}

这将导致级联效果,关闭您的所有活动。

但是,这是一种hack,其使用startActivityForResult方式并非设计为可以使用。

也许更好的方法是使用广播接收器,如下所示:

注销时,清除“活动历史记录”堆栈,以防止“后退”按钮打开仅登录的活动

有关其他方法,请参见以下线程:

Android:清除后盖

完成之前的所有活动


4
当您有大约30个历史活动时,这可行吗?
Rakesh Gondaliya

4
应该。但是,如果您有30项历史记录,那么您可能需要考虑更改设计。30似乎有点太多了,Android可能会杀死他们自己。
Anup Cowkur 2013年

1
这似乎是一个糟糕的方法。@RakeshGondaliya的回答问题似乎合法。30个也许只是代表“大量”活动的数字。这个答案看起来更好:stackoverflow.com/a/3008684/243709
阿曼阿拉姆(Aman Alam)

这个答案很好。您还可以使用EventBus库将事件发送到后台的活动中。github.com/greenrobot/EventBus
Stan,

最好使用带有意图的简单'Intent.FLAG_ACTIVITY_CLEAR_TOP'标志
Naveen Rao

18

要完全清除活动堆栈,您想使用TaskStackBuilder创建一个新的任务堆栈,例如:

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

如果您的LoginActivity具有父活动,这不仅会创建一个新的,干净的任务堆栈,还将使“向上”按钮正常工作。


1
这是最好的方法。
保罗·伯克

FLAG_ACTIVITY_NEW_TASKfinishAffinity()没有为我工作。只有这个答案解决了目的。
TM

如果我通过后退按钮离开应用程序并通过应用程序图标返回,它将在我调用该方法的活动中打开。所以不要为我工作。
Tgo1014

17

finishAffinity()已在API 16中添加。ActivityCompat.finishAffinity()在以前的版本中使用。使用意图启动任何活动并完成当前活动的时间。现在ActivityCompat.finishAffinity()改为使用 finish()。它将完成当前活动之下的所有堆叠活动。这对我来说可以。


3
实际上是ActivityCompat.finishAffinity()
Berga,2016年

finishAffinity()还以相同亲和力的后堆栈中存在的所有活动结束当前活动。
Neeraj Sewani

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();

我这样做了,发生了什么事:当我单击“后退”按钮时,我将带我到来自ProfileActivity的
Activty

发生这种情况的原因是,您通过调用新的意图而不是通过调用finish()来进入ProfileActivity;除了LoginActivty之外,您如何通过其他活动进入ProfileActivity?
Android

我遇到了同样的问题。我认为,由于缺少内存,当登录意图被系统破坏时,它将无法正常工作。
user1914692

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
在API 16中添加了finishAffinity()。在先前版本中使用ActivityCompat.finishAffinity()。我对我来说很好。
Anurag Srivastava 2015年

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

没有任何意图标志对我有用,但这是我解决的方法:

当用户从一个活动中注销时,我必须广播该活动中的消息,然后在我想关闭的活动中接收该消息,此后我调用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_TASKFLAG_ACTIVITY_NEW_TASK在Intent上进行标记以清除所有活动堆栈。

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

先进的可重复使用的Kotlin:

您可以使用setter方法直接设置标志。在Kotlin中,or是按位Java或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
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.