Java 你如何使用 Intent.FLAG_ACTIVITY_CLEAR_TOP 来清除 Activity Stack?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4342761/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 16:11:17  来源:igfitidea点击:

How do you use Intent.FLAG_ACTIVITY_CLEAR_TOP to clear the Activity Stack?

javaandroidandroid-intentandroid-activityandroid-manifest

提问by piusvelte

I've read through several posts about using this, but must be missing something as it's not working for me. My activity A has launchmode="singleTop" in the manifest. It starts activity B, with launchmode="singleInstance". Activity B opens a browser and receives and intent back, which is why it's singleInstance. I'm trying to override the back button so that the user is sent back to the activity A, and can then press Back to leave the activity, rather than back to activity B again.

我已经阅读了几篇关于使用它的帖子,但一定遗漏了一些东西,因为它对我不起作用。我的活动 A 在清单中有 launchmode="singleTop" 。它以launchmode="singleInstance" 启动活动B。Activity B 打开浏览器并接收并返回 Intent,这就是它是 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;
}

After returning from the browser, the stack is... A,B,Browser,B

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

I expect this code to change the stack to... A ... so that pressing back once more takes the user back to the Home Screen.

我希望这段代码将堆栈更改为... A ... 以便再次按回将用户带回主屏幕。

Instead it seems to change the stack to... A,B,Browser,B,A ...as though those flags aren't there.

相反,它似乎将堆栈更改为... A,B,Browser,B,A ...就好像这些标志不存在一样。

I tried calling finish() in activity B after startActivity, but then the back button takes me back to the browser again!

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

What am I missing? Thank you!

我错过了什么?谢谢!

采纳答案by ScouseChris

@bitestar has the correct solution, but there is one more step:

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

It was hidden away in the docs, however you must change the launchModeof the Activityto anything other than standard. Otherwise it will be destroyed and recreated instead of being reset to the top.

它在文档隐藏起来,但是你必须改变launchModeActivity比其他任何东西standard。否则它将被销毁并重新创建,而不是被重置到顶部。

回答by 100rabh

FLAG_ACTIVITY_NEW_TASK is the problem here which initiates a new task .Just remove it & you are done.

FLAG_ACTIVITY_NEW_TASK 是这里启动新任务的问题。只需将其删除即可。

Well I recommend you to read what every Flag does before working with them

好吧,我建议您在使用它们之前阅读每个 Flag 的作用

Read this& Intent Flags here

在此处阅读此内容意图标志

回答by ja_chu

Initially I also had problem getting FLAG_ACTIVITY_CLEAR_TOP to work. Eventually I got it to work by using the value of it (0x04000000). So looks like there's an Eclipse/compiler issue. But unfortunately the surviving activity is restarted, which is not what I want. So looks like there's no easy solution.

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

回答by Jesper Bischoff-Jensen

I have started Activity A->B->C->D. When the back button is pressed on Activity D I want to go to Activity A. Since A is my starting point and therefore already on the stack all the activities in top of A is cleared and you can't go back to any other Activity from A.

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

This actually works in my code:

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

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

回答by Fedir Tsapana

For this, I use FLAG_ACTIVITY_CLEAR_TOPflag for starting Intent
(without FLAG_ACTIVITY_NEW_TASK)

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

and launchMode = "singleTask"in manifest for launched activity.

launchMode = "singleTask"在已启动活动的清单中。

Seems like it works as I need - activity does not restart and all other activities are closed.

似乎它按我的需要工作 - 活动不会重新启动并且所有其他活动都已关闭。

回答by Kevin

I know that there's already an accepted answer, but I don't see how it works for the OP because I don't think FLAG_ACTIVITY_CLEAR_TOP is meaningful in his particular case. That flag is relevant only with activities in the same task. Based on his description, each activity is in its own task: A, B, and the browser.

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

Something that is maybe throwing him off is that A is singleTop, when it should be singleTask. If A is singleTop, and B starts A, then a new A will be created because A is not in B's task. From the documentation for singleTop:

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

"If an instance of the activity already exists at the top of the current task, the system routes the intent to that instance..."

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

Since B starts A, the current task is B's task, which is for a singleInstance and therefore cannot include A. Use singleTask to achieve the desired result there because then the system will find the task that has A and bring that task to the foreground.

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

Lastly, after B has started A, and the user presses back from A, the OP does not want to see either B or the browser. To achieve this, calling finish() in B is correct; again, FLAG_ACTIVITY_CLEAR_TOP won't remove the other activities in A's task because his other activities are all in different tasks. The piece that he was missing, though is that B should also use FLAG_ACTIVITY_NO_HISTORY when firing the intent for the browser. Note:if the browser is already running prior to even starting the OP's application, then of course you will see the browser when pressing back from A. So to really test this, be sure to back out of the browser before starting the application.

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

回答by Darpan

Though this question already has sufficient answers, I thought somebody would want to know why this flag works in this peculiar manner, This is what I found in Android documentation

虽然这个问题已经有足够的答案,但我想有人会想知道为什么这个标志以这种特殊的方式工作,这就是我在Android 文档中找到的

The currently running instance of activity B in the above example will either receive the new intent you are starting here in its onNewIntent() method, or be itself finished and restarted with the new intent.

If it has declared its launch mode to be "multiple" (the default) and you have not set FLAG_ACTIVITY_SINGLE_TOP in the same intent, then it will be finished and re-created; for all other launch modes or if FLAG_ACTIVITY_SINGLE_TOP is set then this Intent will be delivered to the current instance's onNewIntent().

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

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


So, Either,
1. Change the launchModeof the Activity A to something else from standard (ie. singleTaskor something). Then your flag FLAG_ACTIVITY_CLEAR_TOPwill not restart your Activity A.


所以,要么,
1launchMode将活动 A 的内容从标准更改为其他内容(即singleTask或其他内容)。那么您的标志FLAG_ACTIVITY_CLEAR_TOP将不会重新启动您的活动 A。

or,

或者,

2. Use Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOPas your flag. Then it will work the way you desire.

2. 使用Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP为您的标志。然后它会按照你想要的方式工作。

回答by Swap-IOS-Android

i called activity_name.this.finish()after starting new intent and it worked for me.

activity_name.this.finish()在开始新的意图后打电话,它对我有用。

I tried "FLAG_ACTIVITY_CLEAR_TOP" and "FLAG_ACTIVITY_NEW_TASK"

But it won't work for me... I am not suggesting this solution for use but if setting flag won't work for you than you can try this..But still i recommend don't use it

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

回答by Ahmad Aghazadeh

Add android:noHistory="true" in manifest file .

在清单文件中添加 android:noHistory="true" 。

<manifest >
        <activity
            android:name="UI"
            android:noHistory="true"/>

</manifest>

回答by Houssin Boulla

I use three flags to resolve the problem:

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

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