完成所有先前的活动。

421

我的应用程序具有以下流程屏幕:

首页->屏幕1->屏幕2->屏幕3->屏幕4->屏幕5

现在我在每个屏幕上都有一个公共的 退出登录 按钮

(首页/屏幕1/屏幕2/屏幕3/屏幕4/屏幕5)

我希望当用户点击退出登录按钮(无论从哪个屏幕),所有屏幕都将被关闭,并打开一个新的屏幕 登录

我已经尝试过几乎所有的 FLAG_ACTIVITY 来实现这一点。 我也查看了stackoverflow上的一些答案,但无法解决问题。 我的应用程序在Android 1.6上,因此无法使用 FLAG_ACTIVITY_CLEAR_TASK

有没有办法解决这个问题?


你是否使用startActivityForResult来运行嵌套的活动? - woodshy
所有的活动都是通过startActivity开始的。 - Tanmay Mandal
我在使用嵌套活动时,在嵌套活动中运行finishaffinitytask()。这会改变行为吗?因为有时候当finishaffinitytask运行时,我会得到“Failure delivering result ResultInfo”的错误信息。 - Ripal Tamboli
请检查这个答案,它肯定会帮助你 https://dev59.com/OGMl5IYBdhLWcg3wZGPo#25159180 - Kimmi Dhingra
4
Android 21引入了Activity.finishAndRemoveTask()方法。 - Jo Jo
只有使用这些标志才能为我工作:intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); - Alexei
29个回答

603

使用:

Intent intent = new Intent(getApplicationContext(), Home.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

这将清除在主屏幕之上的所有活动。

假设当用户登录时你正在完成登录屏幕并创建主屏幕,之后所有从1到5的屏幕都在主屏幕之上。我发帖的代码将使你回到主屏幕,完成所有其他活动。你可以在意图中添加一个额外的内容,在主屏幕活动中读取并结束它(也许再从那里启动登录屏幕或其他东西)。

我不确定,但你也可以尝试使用此标志进入登录。我不知道在这种情况下活动会如何排序。所以不知道它是否会清除屏幕下面的屏幕,包括你当前所在的屏幕,但这绝对是正确的方式。


1
用户正在将他的第一个屏幕显示为主屏幕,这是主要问题。 - Tanmay Mandal
12
不要使用 singleInstance 来声明活动,可以考虑将 FLAG_ACTIVITY_CLEAR_TOP|FLAG_ACTIVITY_SINGLE_TOP 作为 Intent 的标志。这样会结束干扰的活动并启动(或将所需活动带回前台)。 - CommonsWare
14
在我的活动中添加“intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);”并不能帮助我。它没有完成干扰的活动。当我从登录屏幕按返回键时,我可以看到以前的活动。这是我的代码:“Intent intent = new Intent(BaseActivity.this,Login.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); startActivity(intent);”。 - Tanmay Mandal
37
这段代码只能清除顶部的Activity栈,若要清除所有Activities,则需要添加以下标记:intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK); - Ajay Venugopal
不确定这是否可接受,因为它重新启动了一个活动,而不是仅删除和完成所有活动。 - Jono
显示剩余10条评论

342

你可以尝试使用Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK。它会完全清除所有先前的活动,并启动新的活动。


11
正确的解决方案,但仅适用于API 11以上。 - riwnodennyk
2
@riwnodennyk why API 11+? - Muhammad Babar
17
对于 Android 版本小于 11,使用 IntentCompat.FLAG_ACTIVITY_CLEAR_TASK。 - Steven Pena
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP| IntentCompat.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK); 对我有用,谢谢! - Marcio Granzotto
2
@ono 是的,那应该就是你需要的全部了。请确保你的目标Activity在清单文件中设置了“singleTask”启动模式。 - Steven Pena
显示剩余11条评论

157

在启动新活动之前,只需添加以下代码:

finishAffinity();

或者如果你希望它在较旧版本的安卓中也能正常工作:

ActivityCompat.finishAffinity(this);

12
ActivityCompat.finishAffinity(this); 在 API 版本小于 16 的情况下调用 activity.finish() 方法,因此无法正常工作。 - Aamir Abro
1
@Beto Caldas,我已经确认了源代码,它在API < 16上不起作用,就像AamirAbro所提到的那样。在API < 16上,它只会完成你传递的活动。 - HendraWD
2
至今为止,对于API > 16,这仍然是最佳解决方案,因为其他解决方案在清除或重新创建任务时会产生延迟。 - al kaj

39

当用户希望退出所有打开的活动时,他们应该按下一个按钮,该按钮将加载应用程序启动时运行的第一个活动,清除所有其他活动,然后完成最后剩余的活动。当用户按下退出按钮时,请运行以下代码。在我的情况下,LoginActivity是我程序中第一个运行的活动。

Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("EXIT", true);
startActivity(intent);

上述代码会清除除LoginActivity之外的所有活动。然后在LoginActivityonCreate(...)中放入以下代码,以便监听当LoginActivity被重新创建且传递了“EXIT”信号时:

if (getIntent().getBooleanExtra("EXIT", false)) {
    finish();  
}

为什么在安卓上制作退出按钮如此困难?

安卓系统试图阻止您在应用程序中设置“退出”按钮,因为他们希望用户永远不必关心他们使用的程序是否在后台运行。

安卓系统开发人员希望您的程序能够在意外关闭和手机断电后存活下来,并且当用户重新启动该程序时,用户可以从上次离开的地方继续操作。因此,用户可以在使用您的应用程序时接听电话,并打开需要释放更多资源的地图等应用。

当用户恢复您的应用程序时,他们可以无缝继续操作而没有任何中断。退出按钮可能会削弱活动管理器的控制权,潜在地导致自动管理的安卓程序生命周期出现问题。


37

我想我来晚了,不过这里有一个简单而又简短的答案。

在Activity中有一个finishAffinity()方法,它可以结束当前Activity和所有父级Activity,但只适用于Android 4.1或更高版本。

对于API 16+,请使用:

finishAffinity();

对于低于16的版本,请使用:

ActivityCompat.finishAffinity(YourActivity.this);

希望能帮到你!


简洁明了的答案。 - Arbaz.in

33
Intent intent = new Intent(this, classObject);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);

这适用于所有Android版本。其中IntentCompat是添加在Android支持库中的类。


IntentCompat.FLAG_ACTIVITY_CLEAR_TASK未被识别,请使用Intent而不是IntentCompat - CoolMind

30

使用以下内容进行活动

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

移除片段使用的CLEAR_TASK标记。

希望这对一些人有用。


24

顺便说一句,值得知道的是
这个答案可行 (https://dev59.com/m2w15IYBdhLWcg3w4_7k#13468685)

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

然而这并不起作用

Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

.setFlags()替换掉之前的所有标记,而不是追加新的标记,但.addFlags()则会。

因此,这也可以工作。

Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

1
关于 setFlag 和 addFlag 的区别的解释很好,谢谢。 - Pelanes

22

developer.android.com:

完成此 Activity 及其所有子 Activity,直到返回到先前启动的 Activity。
public void finishAffinity ()

自 API 级别 16 开始添加

结束当前任务中该活动及所有其下立即具有相同关联性的活动。通常在应用程序可以启动到另一个任务(例如从其了解的内容类型的 ACTION_VIEW)且用户使用向上导航从当前任务切换到其自己的任务时使用此选项。在这种情况下,如果用户导航进入第二个应用程序的任何其他活动,则应将所有这些活动从原始任务中删除作为任务切换的一部分。

请注意,此finish不允许您将结果传递回上一个活动,如果您尝试这样做,将会引发异常。


16
如果您的应用程序最小sdk版本为16,则可以使用< strong>finishAffinity() 立即结束当前任务中同亲和性的下方所有活动,包括此活动。
在我的顶部付款屏幕中,这对我很有帮助。移除所有后退堆栈活动。
@Override
public void onBackPressed() {
         finishAffinity();
        startActivity(new Intent(PaymentDoneActivity.this,Home.class));
    } 

http://developer.android.com/reference/android/app/Activity.html#finishAffinity%28%29


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接