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

我已经阅读了几篇关于使用这个的文章,但是一定遗漏了什么,因为它对我不起作用。我的活动 A 在清单中有 launchmode = “ singleTop”。它以 launchmode = “ singleInstance”启动活动 B。活动 B 打开一个浏览器并接收一个返回的意图,这就是为什么它是 singleInstance 的原因。我试图覆盖后退按钮,这样用户就会被发送回活动 A,然后可以按 Back 退出活动,而不是再次返回活动 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,Browser,B

我希望这段代码能将堆栈改为..。 A 这样再按一次就可以把用户带回主屏幕。

相反,它似乎将堆栈改为..。 A,B,Browser,B,A 就好像那些旗子不存在一样。

我尝试在 startActivity 之后调用 activity B 中的 Finish () ,但是后退按钮又把我带回了浏览器!

我错过了什么?

201489 次浏览

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

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

Read this & Intent Flags here

Initially, I also had a 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.

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.

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

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

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

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

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

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

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.

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:

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

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.

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.

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

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


So, Either,
1. Change the launchMode of the Activity A to something else from standard (ie. singleTask or something). Then your flag FLAG_ACTIVITY_CLEAR_TOP will not restart your Activity A.

or,

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

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

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

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

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


</manifest>

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