你如何使用Intent.FLAG_ACTIVITY_CLEAR_TOP清除活动堆栈?

时间:2010-12-03 05:32:52

标签: java android android-intent android-activity android-manifest

我已经阅读了几篇关于使用它的帖子,但必须遗漏一些因为它不适合我。我的活动A在清单中有launchmode =“singleTop”。它启动活动B,启动模式=“singleInstance”。活动B打开浏览器并接收和意图返回,这就是为什么它是singleInstance。我正在尝试覆盖后退按钮,以便用户被发送回活动A,然后可以按返回退出活动,而不是再次返回活动B.

// activity B
@Override
public boolean onKeyDown(int keyCode, KeyEvent event)  {
 if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.ECLAIR
  && keyCode == KeyEvent.KEYCODE_BACK
  && event.getRepeatCount() == 0) onBackPressed();
 return super.onKeyDown(keyCode, event);
}
@Override
public void onBackPressed() {
 startActivity(new Intent(this, UI.class)
 .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK));
 return;
}

从浏览器返回后,堆栈是...... A,B,浏览器,B

我希望这段代码能够将堆栈更改为...... 一个 ...这样再次按下会使用户返回主屏幕。

相反,似乎将堆栈更改为...... A,B,浏览器,B,A ......好像那些旗帜不在那里。

我尝试在startActivity之后调用活动B中的finish(),但后面的按钮再次将我带回浏览器!

我错过了什么?谢谢!

10 个答案:

答案 0 :(得分:103)

我已经开始活动A-> B-> C-> D。 当按下后退按钮时,活动DI想要转到活动A.由于A是我的起点,因此已经在堆栈中,A顶部的所有活动都被清除,你不能回到A的任何其他活动。

这实际上适用于我的代码:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        Intent a = new Intent(this,A.class);
        a.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(a);
        return true;
    }
    return super.onKeyDown(keyCode, event);
}       

答案 1 :(得分:64)

@bitestar有正确的解决方案,但还有一个步骤:

它隐藏在文档中,但您必须将launchMode的{​​{1}}更改为Activity以外的任何内容。否则它将被销毁并重新创建,而不是重置为顶部。

答案 2 :(得分:19)

为此,我使用FLAG_ACTIVITY_CLEAR_TOP标记开始Intent
(没有FLAG_ACTIVITY_NEW_TASK

发布活动的清单中的

launchMode = "singleTask"

似乎它可以正常工作 - 活动不会重新启动,所有其他活动都会关闭。

答案 3 :(得分:10)

虽然这个问题已经有了足够的答案,但我想有人会想知道为什么这个旗子以这种奇特的方式运作,这就是我在Android documentation中找到的

  

上面示例中当前运行的活动B实例将在其onNewIntent()方法中接收您从此处开始的新意图,或者本身已完成并使用新意图重新启动。

如果它已将其启动模式声明为“多个”(默认值)并且您没有在同一意图中设置FLAG_ACTIVITY_SINGLE_TOP,那么它将被完成并重新创建;对于所有其他启动模式或者如果设置了FLAG_ACTIVITY_SINGLE_TOP,则此Intent将被传递到当前实例的onNewIntent()。


所以,要么,
1 即可。将活动A的launchMode更改为标准的其他内容(即singleTask或其他内容)。然后您的国旗FLAG_ACTIVITY_CLEAR_TOP将不会重新启动您的活动A.

,或者

<强> 2 即可。使用Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP作为您的旗帜。然后它会以你想要的方式工作。

答案 4 :(得分:2)

我知道已经有一个已接受的答案,但我不知道它对OP是如何起作用的,因为我不认为FLAG_ACTIVITY_CLEAR_TOP在他的特定情况下是有意义的。该标志仅与相同任务中的活动相关。根据他的描述,每项活动都在其自己的任务中:A,B和浏览器。

可能让他失望的是A是singleTop,当它应该是singleTask时。如果A是singleTop,而B开始A,那么将创建一个新的A,因为A不在B的任务中。来自singleTop的文档:

“如果活动的实例已经存在于当前任务的顶部,系统会将意图路由到该实例......”

由于B启动A,当前任务是B的任务,这是针对singleInstance的,因此不能包含A.使用singleTask在那里实现所需的结果,因为系统将找到具有A的任务并将该任务带到前景。

最后,在B启动A并且用户从A按下后,OP不希望看到B或浏览器。为此,在B中调用finish()是正确的;再次,FLAG_ACTIVITY_CLEAR_TOP将不会删除A任务中的其他活动,因为他的其他活动都在不同的任务中。但他缺少的部分是B在触发浏览器的意图时也应该使用FLAG_ACTIVITY_NO_HISTORY。 注意:如果浏览器在启动OP的应用程序之前已经在运行,那么当然从A回来时你会看到浏览器。所以要真正测试这个,一定要退出启动应用程序之前的浏览器。

答案 5 :(得分:2)

添加android:noHistory =&#34; true&#34;在清单文件中。

global
    log 127.0.0.1 local0 notice
    user haproxy
    group haproxy

defaults
    log global
    retries 2
    timeout connect 3000
    timeout server 5000
    timeout client 5000

listen mysql-cluster
    bind 0.0.0.0:3306
    mode tcp
    option tcplog
    log global
    option mysql-check user haproxy_check
    balance roundrobin
    server database1 10.2.10.102:3306 check
    server database2 10.2.10.103:3306 check
    server database3 10.2.10.104:3306 check

答案 6 :(得分:2)

我使用三个标志来解决问题:

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

答案 7 :(得分:1)

FLAG_ACTIVITY_NEW_TASK是此处启动新任务的问题。除去它&amp;你完成了。

我建议你在使用它们之前阅读每个Flag的内容

阅读this&amp; Intent Flags here

答案 8 :(得分:1)

最初,我也遇到了使FLAG_ACTIVITY_CLEAR_TOP正常工作的问题。最终我通过使用它的值(0x04000000)使它工作。所以看起来有一个Eclipse /编译器问题。但不幸的是,幸存的活动重新开始,这不是我想要的。所以看起来没有简单的解决方案。

答案 9 :(得分:1)

我在启动新意图后调用了activity_name.this.finish(),它对我有用。

I tried "FLAG_ACTIVITY_CLEAR_TOP" and "FLAG_ACTIVITY_NEW_TASK"

但它对我不起作用......我不是建议使用这个解决方案,但如果设置标志对你不起作用,你可以尝试这个..但我仍然建议不要使用它