Android:清除活动堆栈


132

我的应用程序中有几个活动。而且流程非常复杂。当我单击注销应用程序时,导航到登录屏幕,然后用户可以通过取消按钮(调用system.exit(0))退出

当我退出或返回按钮时,系统从堆栈中调用一个活动:(当我进入“登录”屏幕时,如何清除堆栈中的所有活动?调用finish()是不实际的,因为有太多活动,并且某些活动不应在关闭时关闭它们是活动的,例如本地相机调用活动。

validateuser logoutuser = new validateuser();
logoutuser.logOut();
Intent loginscreen = new Intent(homepage.this, Login2.class);
(homepage.this).finish();
loginscreen.setFlags( Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(loginscreen);


Answers:


339

你们大多数人是错的。如果要关闭现有活动堆栈,而不管其中有什么内容,并创建新的根目录,则正确的标志集如下:

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

从文档

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

如果在传递给的Intent中设置 Context.startActivity(),则此标志将导致在活动开始之前清除与该活动相关的任何现有任务。也就是说,该活动成为原本空任务的新根,并且所有旧活动都已完成。只能与结合使用FLAG_ACTIVITY_NEW_TASK


工作完美。谢谢。奇怪的是,minSDK = 9时没有给出错误。
Mahm00d 2014年

坦白地说,我从没使用过此功能,在崩溃后会复活等等,而是专注于解决导致崩溃的问题)
Cynichniy Bandera 2015年

IntentCompat.makeRestartActivityTask支持库也提供相同的功能。
Sealskej

仅添加这两个标志会留下活动堆栈轨迹(从上一个标志开始),然后添加Intent.FLAG_ACTIVITY_CLEAR_TOP,它仅重新启动应用程序,然后完全退出。我还没有明确地向活动添加任何标志。可能是什么问题呢?
Farid

1
最好的开端之一:“你们中大多数人错了。”
nibbana

31

当您调用startActivity上一个活动时,您可以随时使用

Intent.FLAG_ACTIVITY_CLEAR_TOP

作为该意图的标志。

此处阅读有关该标志的更多信息。


这也无济于事。我只是提出了一个活动,它没有以finish()结尾;:(
杰·马尤

我猜FLAG_ACTIVITY_CLEAR_TOP清除了顶部的活动。我的问题是底部的活动:(
杰伊·马尤

我想这取决于流程的实际情况。:你应该阅读更多关于它在这里developer.android.com/reference/android/content/...developer.android.com/guide/topics/fundamentals/...
大卫·奥尔森

7
感谢您显示正确的资源。我犯的错误是关闭登录活动。我不应该关闭它。活动首次加载时。因此,当我使用Clear_top标志将其回调时,登录活动会清除顶部的所有活动。由于登录是第一个entrace活动,因此它将清除之后开始的所有活动。所以宾果游戏成功了:)
杰伊·马尤

13
从文档中,仅当特定活动“已在当前任务中运行”时
FLAG_ACTIVITY_CLEAR_TOP

16

这是一个简单的帮助程序方法,用于启动新活动作为新的顶级活动,该活动从API级别4一直到当前版本17为止:

static void startNewMainActivity(Activity currentActivity, Class<? extends Activity> newTopActivityClass) {
    Intent intent = new Intent(currentActivity, newTopActivityClass);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
        intent.addFlags(0x8000); // equal to Intent.FLAG_ACTIVITY_CLEAR_TASK which is only available from API level 11
    currentActivity.startActivity(intent);
}

从您当前的活动中这样称呼它:

startNewMainActivity(this, MainActivity.class);

1
总而言之,您不能只使用intent.addFlags(0x8000);吗?简化一下?
达沃

由于此标志是在Honeycomb中首次引入的,所以我不知道它对较早版本的含义。所以,这是我的事。但是我想去除调味品应该不是问题。
2013年

1
要添加标志时,API等级<11,那么你需要做Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB别的intent.addFlags(0x8000);永远不会增加
草帽

我让用户通过意图接连进行许多活动。为了确保应用程序不会因堆栈上的太多活动而崩溃,我是否需要做任何事情?谢谢!
Ruchir Baronia 2015年

9

通过以下代码清除Activity Backstate

Intent intent = new Intent(Your_Current_Activity.this, Your_Destination_Activity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK |Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

完成了


我让用户通过意图接连进行许多活动。为了确保应用程序不会因堆栈上的太多活动而崩溃,我是否需要做任何事情?谢谢!
Ruchir Baronia 2015年

@RuchirBaronia,如果您转到A-> B-> C-> D-> E-> F-> G-> H,现在是H->我写的代码比最后一个活动写的要多,然后按Back按钮应用程式即将关闭,因为应用程式没有后台活动,希望这对您有帮助。
埃伦·帕特尔

我是否需要这样做?如果我从不清理活动堆栈,该怎么办?
Ruchir Baronia 2015年

@ RuchirBaronia,Backpress:H-> G-> F-> E-> D-> C-> B-> A
Hiren Patel 2015年

但是有时它在调用新活动时显示白屏。何解决这个问题?
萨加尔'18

4

就我而言,LoginActivity也已关闭。结果是,

Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK

没有帮助。

但是,设置

Intent.FLAG_ACTIVITY_NEW_TASK

帮助过我。


我让用户通过意图接连进行许多活动。为了确保应用程序不会因堆栈上的太多活动而崩溃,我是否需要做任何事情?谢谢!
Ruchir Baronia 2015年


3

我注意到您要求的解决方案不依赖finish(),但我想知道这是否仍然有帮助。

我跟踪了是否使用静态类变量引发了退出标志,该变量在整个应用程序生命周期中都可以生存。在每个相关活动中onResume(),使用

@Override
public void onResume() {
    super.onResume();
    if (ExitHelper.isExitFlagRaised) {
        this.finish();
    }
}

ExitHelper类

public class ExitHelper {
    public static boolean isExitFlagRaised = false;
}

假设在mainActivity中,用户按下按钮退出-您可以先设置ExitHelper.isExitFlagRaised = true;,然后再设置finish()。此后,其他自动恢复的相关活动也将完成。


如果我在MainActivity onresume()中使用代码,然后从第二个活动onbackpress返回到mainactivity,将会发生什么情况
Mithu

3

这个决定很好用:

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

但是新活动启动时间很长,一段时间后您会看到白屏。如果这很关键,请使用以下解决方法:

public class BaseActivity extends AppCompatActivity {

    private static final String ACTION_FINISH = "action_finish";

    private BroadcastReceiver finisBroadcastReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        registerReceiver(finisBroadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                finish();
            }
        }, new IntentFilter(ACTION_FINISH));
    }

    public void clearBackStack() {
        sendBroadcast(new Intent(ACTION_FINISH));
    }

    @Override
    protected void onDestroy() {
        unregisterReceiver(finisBroadcastReceiver);
        super.onDestroy();
    }
}

使用方法:

public class ActivityA extends BaseActivity {

    // Click any button
    public void startActivityB() {
        startActivity(new Intent(this, ActivityB.class));
        clearBackStack();
    }
}

缺点:必须在堆栈上关闭的所有活动都必须扩展BaseActivity


2

对于Xamarin开发人员,您可以使用:

intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.ClearTask);

1

使用Kotlin:

您可以使用setter方法直接设置标志。在Kotlin中,or是按位Java或Java 的替代品|

intent.flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK

如果您打算定期使用此功能,请创建一个Intent扩展功能

fun Intent.clearStack() {
    flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}

然后,您可以在启动意图之前直接调用此函数

intent.clearStack()
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.