从历史堆栈中删除活动

问题描述 投票:363回答:14

我的应用在用户首次运行应用时显示了注册活动,如下所示:

  1. ActivitySplashScreen(欢迎来到游戏,注册一个帐户?)
  2. ActivitySplashScreenSignUp(很棒,请填写此信息)
  3. ActivityGameMain(主游戏画面)

因此,当用户点击每个屏幕上的按钮时,活动将以完全相同的顺序相互启动。

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

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

谢谢

android android-activity activity-lifecycle
14个回答
612
投票

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

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

4
投票

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

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

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

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


3
投票

对于API> = 15到API 23,其他解决方案在我的情况下不起作用。最后我得到了这个。

 Intent nextScreen = new Intent(currentActivity.this, MainActivity.class);
 nextScreen.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
 startActivity(nextScreen);
 ActivityCompat.finishAffinity(currentActivity.this);

3
投票

现在为时已晚,但希望它有所帮助。大多数答案都没有指向正确的方向。这样的事情有两个简单的标志。

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

来自Android文档:

public static final int FLAG_ACTIVITY_CLEAR_TASK在API级别11中添加

If set in an Intent passed to Context.startActivity(), this flag will cause any existing task that would be associated with the

活动开始前要清除的活动。也就是说,活动成为否则为空任务的新根,并且任何旧活动都已完成。这只能与FLAG_ACTIVITY_NEW_TASK一起使用。


1
投票

只需在startActivity(intent)之前调用this.finish(),就像这样 -

       Intent intent = new Intent(ActivityOne.this, ActivityTwo.class);
        this.finish();
        startActivity(intent);

-7
投票

试试这个:

intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY)

它是API等级1,检查link


135
投票

您可以使用转发从活动堆栈中删除以前的活动,同时启动下一个活动。 There's an example of this in the APIDemos,但基本上你所做的就是在打电话给finish()后立即打电话给startActivity()


50
投票

23
投票

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

在每个班级,你想要在晴朗的时候离开,你需要这样做:

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

然后需要从堆栈中引发弹出链的那个需要在你想要启动时调用它:

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

然后活动不在堆栈上! 记住,你可以开始一个活动,然后开始清理它,执行不遵循单个(ui)线程。


21
投票

在API 11之前工作的一种方法是首先启动ActivityGameMain,然后在该Activity的onCreate中启动你的ActivitySplashScreen活动。 ActivityGameMain不会出现,因为你很快就会调用startActivity。

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

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

您还必须将其添加到ActivitySplashScreen:

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

因此,回击该活动不会回到你的ActivityGameMain

我假设你不希望启动画面回到任何一个,为了达到这个目的,我建议将它设置为你的noHistory中的AndroidManifest.xml。然后将goBackPressed代码放入ActivitySplashScreenSignUp类中。

但是我发现了一些方法来打破这个。在显示ActivitySplashScreenSignUp并且未重置后退历史记录时,从通知启动另一个应用程序。

API 11中唯一真正的解决方法是:

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);

17
投票

我用这种方式。

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

8
投票

我知道我迟到了(问题问题已经过去两年了)但是我通过拦截后退按钮完成了这个。我只是查看计数,而不是检查特定的活动,如果它小于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();
    }
}

6
投票

只需在Manifest文件中设置noHistory="true"即可。它使活动从后台堆栈中删除。


6
投票

在清单中,您可以添加:

android:noHistory="true"

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

你也可以打电话

finish()

调用startActivity(..)后立即

© www.soinside.com 2019 - 2024. All rights reserved.