Android 从历史堆栈中删除活动

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1898886/
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-20 03:46:16  来源:igfitidea点击:

Removing an activity from the history stack

androidandroid-activityactivity-lifecycle

提问by Mark

My app shows a signup activity the first time the user runs the app, looks like:

我的应用程序在用户第一次运行应用程序时显示注册活动,如下所示:

  1. ActivitySplashScreen (welcome to game, sign up for an account?)
  2. ActivitySplashScreenSignUp (great, fill in this info)
  3. ActivityGameMain (main game screen)
  1. ActivitySplashScreen(欢迎来到游戏,注册账号?)
  2. ActivitySplashScreenSignUp(很好,填写此信息)
  3. ActivityGameMain(主游戏画面)

so the activities launch each other in exactly that order, when the user clicks through a button on each screen.

因此,当用户单击每个屏幕上的按钮时,这些 Activity 会以完全相同的顺序相互启动。

When the user goes from activity #2 to #3, is it possible to wipe #1 and #2 off the history stack completely? I'd like it so that if the user is at #3, and hits the back button, they just go to the homescreen, instead of back to the splash screen.

当用户从活动#2 转到#3 时,是否可以将#1 和#2 从历史堆栈中完全擦除?我希望这样,如果用户在#3,并点击后退按钮,他们只是转到主屏幕,而不是回到初始屏幕。

I think I can accomplish this with tasks (ie. start a new task on #3) but wanted to see if there was simpler method,

我想我可以用任务来完成这个(即在#3 上开始一个新任务)但想看看是否有更简单的方法,

Thanks

谢谢

回答by Aitor Gómez

You can achieve this by setting the android:noHistoryattributeto "true"in the relevant <activity>entries in your AndroidManifest.xmlfile. For example:

您可以通过在文件的相关条目中设置android:noHistory属性来实现此目的。例如:"true"<activity>AndroidManifest.xml

<activity
    android:name=".AnyActivity"
    android:noHistory="true" />

回答by Dan Lew

You can use forwarding to remove the previous activity from the activity stack while launching the next one. There's an example of this in the APIDemos, but basically all you're doing is calling finish()immediately after calling startActivity().

您可以在启动下一个活动时使用转发从活动堆栈中删除前一个活动。 在 APIDemos 中有一个这样的例子,但基本上你所做的就是在调用finish()之后立即调用startActivity()

回答by Matthias

回答by Travis

This is likely not the ideal way to do it. If someone has a better way, I will be looking forward to implementing it. Here's how Iaccomplished this specific task with pre-version-11 sdk.

这可能不是理想的方法。如果有人有更好的方法,我将期待实施它。这是如何使用 pre-version-11 sdk 完成此特定任务的方法。

in each class you want to go away when it's clear time, you need to do this:

在每节课中你想在时间到的时候离开,你需要这样做:

    ... interesting code stuff ...
    Intent i = new Intent(MyActivityThatNeedsToGo.this, NextActivity.class);
    startActivityForResult(i, 0);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == R.string.unwind_stack_result_id) {
        this.setResult(R.string.unwind_stack_result_id);
        this.finish();
    }
}

then the one that needs to set off the chain of pops from the stack needs to just call this when you want to initiate it:

那么需要从堆栈中触发弹出链的那个需要在您想要启动它时调用它:

NextActivity.this.setResult(R.string.unwind_stack_result_id);
NextActivity.this.finish();

Then the activities aren't on the stack!
Remember folks, that you can start an activity, and then begin cleaning up behind it, execution does not follow a single (the ui) thread.

那么活动不在堆栈中!
请记住,您可以启动一个活动,然后开始在它后面进行清理,执行不遵循单个(ui)线程。

回答by mxcl

One way that works pre API 11 is to start ActivityGameMainfirst, then in the onCreateof that Activity start your ActivitySplashScreenactivity. The ActivityGameMainwon't appear as you call startActivity too soon for the splash.

在 API 11 之前工作的一种方法是首先启动ActivityGameMain,然后在该onCreateActivity 中启动您的ActivitySplashScreenActivity。在ActivityGameMain你太早飞溅调用startActivity将不会出现。

Then you canclear the stack when starting ActivityGameMainby setting these flags on the Intent:

然后你可以在开始时ActivityGameMain通过在 Intent 上设置这些标志清除堆栈:

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

You also must add this to ActivitySplashScreen:

您还必须将其添加到 ActivitySplashScreen:

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

So that pressing back on that activity doesn't go back to your ActivityGameMain.

因此,按回该活动不会回到您的ActivityGameMain.

I assume you don't want the splash screen to be gone back to either, to achieve this I suggest setting it to noHistoryin your AndroidManifest.xml. Then put the goBackPressedcode in your ActivitySplashScreenSignUpclass instead.

我假设您也不希望启动画面返回,为了实现这一点,我建议将它设置为noHistory您的AndroidManifest.xml. 然后将goBackPressed代码放在您的ActivitySplashScreenSignUp班级中。

However I have found a few ways to break this. Start another app from a notification while ActivitySplashScreenSignUpis shown and the back history is not reset.

但是,我找到了一些方法来打破这种情况。ActivitySplashScreenSignUp显示时从通知启动另一个应用程序,并且不会重置返回历史记录。

The only real way around this is in API 11:

解决这个问题的唯一真正方法是在 API 11 中:

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);

回答by Smiderle

I use this way.

我用这种方式。

Intent i = new Intent(MyOldActivity.this, MyNewActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(i);

回答by alphonzo79

I know I'm late on this (it's been two years since the question was asked) but I accomplished this by intercepting the back button press. Rather than checking for specific activities, I just look at the count and if it's less than 3 it simply sends the app to the back (pausing the app and returning the user to whatever was running before launch). I check for less than three because I only have one intro screen. Also, I check the count because my app allows the user to navigate back to the home screen through the menu, so this allows them to back up through other screens like normal if there are activities other than the intro screen on the stack.

我知道我在这件事上迟到了(自从提出这个问题已经两年了)但是我通过拦截后退按钮来实现这一点。而不是检查特定的活动,我只看计数,如果它小于 3,它只是将应用程序发送到后面(暂停应用程序并将用户返回到启动前正在运行的任何内容)。我检查不到三个,因为我只有一个介绍屏幕。此外,我检查了计数,因为我的应用程序允许用户通过菜单导航回主屏幕,因此如果堆栈上有介绍屏幕以外的活动,则这允许他们像往常一样通过其他屏幕进行备份。

//We want the home screen to behave like the bottom of the activity stack so we do not return to the initial screen
//unless the application has been killed. Users can toggle the session mode with a menu item at all other times.
@Override
public void onBackPressed() {
    //Check the activity stack and see if it's more than two deep (initial screen and home screen)
    //If it's more than two deep, then let the app proccess the press
    ActivityManager am = (ActivityManager)this.getSystemService(Activity.ACTIVITY_SERVICE);
    List<RunningTaskInfo> tasks = am.getRunningTasks(3); //3 because we have to give it something. This is an arbitrary number
    int activityCount = tasks.get(0).numActivities;

    if (activityCount < 3)
    {
        moveTaskToBack(true);
    }
    else
    {
        super.onBackPressed();
    }
}

回答by Anubhav

In the manifest you can add:

在清单中,您可以添加:

android:noHistory="true"

<activity
android:name=".ActivityName"
android:noHistory="true" />

You can also call

你也可以打电话

finish()

immediately after calling startActivity(..)

立即调用 startActivity(..)

回答by Stanislaw Brzezinski

Just set noHistory="true"in Manifestfile. It makes activity being removed from the backstack.

只需noHistory="true"清单文件中设置。它使活动从后台堆栈中删除。

回答by Rowland Mtetezi

It is crazy that no one has mentioned this elegant solution. This should be the accepted answer.

没有人提到这个优雅的解决方案真是太疯狂了。这应该是公认的答案。

SplashActivity -> AuthActivity -> DashActivity

SplashActivity -> AuthActivity -> DashActivity

if (!sessionManager.isLoggedIn()) {
    Intent intent = new Intent(context, AuthActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
    context.startActivity(intent);
    finish();
} else {
   Intent intent = new Intent(context, DashActivity.class);
   context.startActivity(intent);
    finish();
}

The key here is to use intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);for the intermediary Activity. Once that middle link is broken, the DashActivitywill the first and last in the stack.

这里的关键是intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);用于中介Activity。一旦中间链接被破坏,DashActivity将成为堆栈中的第一个和最后一个。

android:noHistory="true"is a bad solution, as it causes problems when relying on the Activityas a callback e.g onActivityResult. This is the recommended solution and should be accepted.

android:noHistory="true"是一个糟糕的解决方案,因为它在依赖Activity作为回调时会导致问题,例如onActivityResult. 这是推荐的解决方案,应该被接受。