如何清除安卓活动栈?

54
我在Android中有一个应用程序,其中包括多个活动,我希望用户可以通过按一个菜单按钮来注销。我遇到的问题是:
A)Android不允许您终止应用程序,并且
B)即使我将用户发送到LoginActivity,他们仍然可以按返回键并立即返回到之前所在的活动。
我已经尝试使用以下两个标志启动Activity:
Intent intent  = new Intent(this, LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);        
startActivity(intent);

我也分别尝试了它们每一个。

我也尝试过在startActivity(intent)之后调用finish(),因为我在另一个StackOverflow问题中看到过这样的做法。


你必须在清单文件中将你的活动声明为 singleinstance。 - Falmarri
类似于Android:清除后退堆栈 - Richard Le Mesurier
10个回答

42

应该进行位或(Bitwise OR)操作,否则将覆盖先前的标志。

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

就像这样:

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

我已经尝试了很多次,但没有得到所需的结果。请帮帮我。 - amity
30
唯一的方式是如果你试图启动的活动已经在活动堆栈中。安卓,你为什么这么奇怪? - mxcl
这个无法在API级别小于11的情况下工作。请查看我的答案,以获取符合API级别>=1的解决方案。 - Luca Fagioli
好的,我有一个用户不断在活动之间切换,这意味着他们可能在20秒内切换了15个活动。这可能会导致内存错误吗?我该怎么做才能解决它?谢谢! - Ruchir Baronia

36
在您的登录活动中,覆盖后退按钮,使其隐藏您的应用程序而不是结束该活动:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        moveTaskToBack(true);
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

同时确保在根Activity上设置android:alwaysRetainTaskState="true",这样Android就不会在用户30分钟不活动后清除您的任务栈(包括登录Activity)。

成功登录后,只需调用finish()即可。


8
谢谢,你的代码让我找到了正确的方向,但是以下代码也可以达到同样的效果:@Override public void onBackPressed(){ moveTaskToBack(true); } - Totic
好的,我有一个用户不断在活动之间切换,这意味着他们可能在20秒内切换了15个活动。这可能会导致内存错误吗?我该怎么做才能解决它?谢谢! - Ruchir Baronia

31
根据 WakkaRemoving an activity from the history stack 中所述,需在 AndroidManifest.xml<activity> 标签中添加android:noHistory="true" 属性,示例如下:
<activity android:name=".MyActivity"
    android:noHistory="true">
</activity>

2
完美!这很简单。 - Nagaraj Alagusundaram

6
如果您正在使用Android API 11或更高版本,您可以使用以下代码清除堆栈。
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);

好的,我有一个用户不断在活动之间切换,这意味着他们可能在20秒内切换了15个活动。这可能会导致内存错误吗?我该怎么做才能解决它?谢谢! - Ruchir Baronia

5

这不会清除您的活动回退栈。

即使按照以上所有答案操作,当我按下返回按钮时,它仍会在关闭应用程序前显示最后一个活动。

这是我所做的:

@Override
public void onBackPressed() { 
    Intent startMain = new Intent(Intent.ACTION_MAIN);
    startMain.addCategory(Intent.CATEGORY_HOME);
    startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(startMain);
}

现在我的应用程序按返回键可以正常退出,没有任何麻烦。

请记住,在比较答案时,Froyo和Cupcake的SDK版本之间发生了很多变化。换句话说,2010年某种方式工作的东西现在可能会有所不同。 - Brandon
是的,你说得对。我会记住的。谢谢。 - amalBit
好的,所以我有一个用户不断在活动之间切换,这意味着他们可能在20秒内切换了15个活动。这可能是导致内存错误的原因吗?我应该怎么解决这个问题?谢谢! - Ruchir Baronia

3

在我处理一个非常类似的情况时,Intent.FLAG_ACTIVITY_CLEAR_TOP设置对我有用,我没有设置Intent.FLAG_ACTIVITY_NEW_TASK标志。你试过不设置吗?


2
这对我有用 :)
Intent main = new Intent(this, A_Activity.class);
main.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
    | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(main);

Intent tool = new Intent(this, B_Activity.class);
startActivity(tool);
finish();

这里的A是我的根活动,例如:

我有活动A->B->C->D,当我在栈上调用启动活动E时,现在我有A->E。

我不知道这是否好:), 但是它可以工作。


好的,我有一个用户不断在活动之间切换,这意味着他们可能在20秒内切换了15个活动。这可能会导致内存错误吗?我该怎么做才能解决它?谢谢! - Ruchir Baronia
@RuchirBaronia 这不应该导致内存不足。可能有些东西正在保留您的活动在内存中 :) 请检查:http://blogs.innovationm.com/android-out-of-memory-error-causes-solution-and-best-practices/ - Gelldur

1

试试这个

Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(
    Intent.FLAG_ACTIVITY_CLEAR_TOP | 
    Intent.FLAG_ACTIVITY_CLEAR_TASK | 
    Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

1
Intent intent  = new Intent(this, LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);        
startActivity(intent);

请注意:必须首先作为启动器启动LoginActivity
如果您编写任何启动器模式,则标志将被覆盖其目的,因此请删除launchermode并尝试,您肯定会成功。

0
如果我们使用这段代码来启动登录活动(A):
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);

活动应该在活动堆栈中,否则这些标志将不会产生任何效果。

如果我们在登录活动(A)中使用finish(),在启动活动(B)后(为了避免从B返回A),活动A(登录)将不在堆栈中。当登录活动具有“noHistory”属性时,情况完全相同。

因此,对我来说解决办法是其他答案的混合体:

此代码放置在活动B中,以避免返回登录活动:

@Override
public void onBackPressed() {
    moveTaskToBack(true);
    super.onBackPressed();
}

这段代码放在调用注销函数的活动中:

public static void logout() {
    Intent intent = new Intent(activity, LoginMain.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
    startActivity(intent);
}

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