完成之前的所有活动


368

我的应用程序具有以下流程屏幕:

Home->screen 1->screen 2->screen 3->screen 4->screen 5

现在我log out 在每个屏幕上都有一个通用按钮

Home/ screen 1 / screen 2 /screen 3/ screen 4 / screen 5

我希望当用户单击注销按钮(从任何屏幕)时,所有屏幕都将完成,并且Log in将打开一个新屏幕。

我几乎已经尝试了所有方法FLAG_ACTIVITY来实现这一目标。我也在stackoverflow中经历了一些答案,但无法解决问题。我的应用程序位于Android 1.6上,因此无法使用FLAG_ACTIVITY_CLEAR_TASK

有什么办法解决这个问题?


您是否使用startActivityForResult运行嵌套活动?
woodshy 2011年

否。所有活动均以startActivity开始。
Tanmay Mandal

我在cod在嵌套活动中运行finishaffinitytask()时使用嵌套活动。它会改变行为吗?有时我会在finishaffinitytask运行时无法交付结果ResultInfo时失败。
Ripal Tamboli 2015年

请检查此答案,它一定会帮助您stackoverflow.com/a/25159180/2732632
Kimmi Dhingra 2015年

3
Android 21引入了Activity.finishAndRemoveTask()。
约瑟夫·约翰逊

Answers:


543

采用:

Intent intent = new Intent(getApplicationContext(), Home.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

这将清除家庭顶部的所有活动。

假设您在用户登录并创建主页后完成登录屏幕,然后在该屏幕之上创建从1到5的所有屏幕。我发布的代码将使您返回主屏幕,完成所有其他活动。您可以在意图中添加其他内容,并在主屏幕活动中阅读并完成它(也可以从那里再次启动登录屏幕等)。

我不确定,但您也可以尝试使用此标志登录。我不知道在这种情况下如何安排活动。因此,不知道它是否会清除屏幕上正在显示的内容,包括当前正在使用的内容,但这绝对是可以解决的方法。

希望这可以帮助。


用户正在将他的第一个屏幕显示为主屏幕,这就是主要问题。
Tanmay Mandal

以及我收到我的答复后,您需要返回主屏幕并完成该操作。因此该过程可以从任何屏幕调用以上意图。在主屏幕上接收到该意图,并在startActivity方法之后立即取消对登录的意图并完成主页。您也可以将待处理的动画覆盖为空,以使进和出为空,这样它就不会显示过渡效果(我这样做是因为感觉比较快)。因此对于您需要的东西应该可以正常工作。
DArkO 2011年

10
与其将活动声明为singleInstance,不如考虑将其FLAG_ACTIVITY_CLEAR_TOP|FLAG_ACTIVITY_SINGLE_TOP用作Intent的标志。这将完成干预活动,并开始(或回到前台)所需的活动。
CommonsWare

13
@ CommonsWare添加intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);到我的活动中没有帮助我。它没有完成干预的活动。当我从“登录”屏幕按回时,可以看到以前的活动。这是我的代码Intent intent=new Intent(BaseActivity.this, Login.class);intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);startActivity(intent);
Tanmay Mandal

26
此代码仅清除顶部活动堆栈,以清除所有活动intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
Ajay Venugopal

318

你可以试试看Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK。它将完全清除所有先前的活动并开始新的活动。


11
正确的解决方案,但只有API 11+
riwnodennyk

我最终使用了这个额外的标志,因为它在显示主要活动时不会引起延迟(它不会重新启动它,因此速度更快)。
毛里齐奥2014年

2
@riwnodennyk为什么使用API​​ 11+?
穆罕默德·巴巴尔

17
将IntentCompat.FLAG_ACTIVITY_CLEAR_TASK用于11个之前的版本
Steven Pena

2
@ono是的。那应该是您所需要的。确保清单中目标活动的启动模式设置为“ singleTask”。
史蒂文·佩纳

137

在启动新的活动之前,只需添加以下代码:

finishAffinity();

或者,如果您希望它在早期版本的Android中运行:

ActivityCompat.finishAffinity(this);

12
ActivityCompat.finishAffinity(this); 为api <16调用activity.finish(),因此它将无法正常工作。
阿米尔阿布(Aamir Abro)2014年

1
@Beto Caldas,我已经本人确认了源代码,如AamirAbro所述,它不适用于<16的API。它将完成您在API <16上传递的活动
。– HendraWD

39

当用户希望退出所有打开的活动时,他们应该按下一个按钮,该按钮将加载在应用程序启动时运行的第一个活动,清除所有其他活动,然后完成最后剩余的活动。当用户按下退出按钮时,请运行以下代码。就我而言,LoginActivity是程序中第一个要运行的活动。

Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("EXIT", true);
startActivity(intent);

上面的代码清除以外的所有活动LoginActivity。然后将以下代码放入LoginActivity的中onCreate(...),以侦听何时LoginActivity重新创建并传递了“退出”信号:

if (getIntent().getBooleanExtra("EXIT", false)) {
    finish();  
}

为什么要使Android中的退出按钮如此困难?

Android会努力阻止您在应用程序中使用“退出”按钮,因为他们希望用户从不关心自己使用的程序是否在后台运行。

Android OS开发人员希望您的程序能够在手机意外关机和关机后继续运行,当用户重新启动该程序时,他们会在停下来的地方重新启动。因此,用户在使用您的应用程序时可以接听电话,并打开地图,这需要释放您的应用程序以获取更多资源。

当用户恢复您的应用程序时,他们会从中断处继续接听,而不会受到干扰。此退出按钮占用了活动管理器的电源,可能会导致自动管理的android程序生命周期出现问题。


31
Intent intent = new Intent(this, classObject);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);

这将适用于所有Android版本。其中IntentCompat的类支持Android库添加。


IntentCompat.FLAG_ACTIVITY_CLEAR_TASK无法识别,请使用Intent代替IntentCompat
CoolMind

30

使用以下活动

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

删除CLEAR_TASK标志以供片段使用。

我希望这对某些人有用。


24

我想我来晚了,但是答案很简单。Activity中有一个finishAffinity()方法可以完成当前活动和所有父活动,但仅在Android 4.1或更高版本中有效。

对于API 16+,请使用

finishAffinity();

16岁以下使用

ActivityCompat.finishAffinity(YourActivity.this);

希望能帮助到你!


21

来自developer.android.com

public void finishAffinity ()

在API级别16中添加

完成此活动以及当前任务中紧接其下的所有具有相同关联性的活动。通常,当可以将应用程序启动到另一个任务上时(例如从它了解的内容类型的ACTION_VIEW启动),并且用户已使用向上导航键切换到当前任务并切换到自己的任务时,通常使用此方法。在这种情况下,如果用户已导航到第二个应用程序的任何其他活动,则应将所有这些活动从原始任务中删除,作为任务切换的一部分。

请注意,完成此操作后,您无法将结果传递到上一个活动,如果尝试这样做,将引发异常。


19

从侧面讲,很高兴知道
这个答案有效(https://stackoverflow.com/a/13468685/7034327

Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
this.finish();

而这不起作用

Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

.setFlags() 替换任何先前的标志,并且在不附加任何新标志的同时.addFlags()

所以这也可以

Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

关于setFlag与addFlag之间的区别的出色解释,谢谢
Pelanes

13

如果您的应用程序的最低SDK版本为16,则可以使用 finishAffinity()

完成此活动以及当前任务中紧接其下的所有具有相同关联性的活动。

这对我来说是正常的工作在“顶部付款”屏幕中,删除所有后退活动,

@Override
public void onBackPressed() {
         finishAffinity();
        startActivity(new Intent(PaymentDoneActivity.this,Home.class));
    } 

http://developer.android.com/reference/android/app/Activity.html#finishAffinity%28%29


10

为此我实现了一个解决方案(我想我是在某个地方的Stack Overflow上找到它的,但是我不记得了,所以要感谢首先这样做的人):

从您的任何活动中执行以下操作:

// Clear your session, remove preferences, etc.
Intent intent  = new Intent(getBaseContext(), LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

然后在您的LoginActivity中,覆盖onKeyDown:

public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        moveTaskToBack(true);
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

3
这通常是一个非常糟糕的主意,可能会起作用,它会引入一个将来可能会中断的联系点,并且很难调试。我是根据经验告诉您的:)
Martin Marconcini 2013年

10

对于应用程序最后一个屏幕上的注销按钮,请在注销按钮侦听器上使用此代码完成所有打开的先前活动,即可解决您的问题。

{
Intent intent = new Intent(this, loginScreen.class);
ntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
}

8
    Intent i1=new Intent(getApplicationContext(),StartUp_Page.class);
i1.setAction(Intent.ACTION_MAIN);
i1.addCategory(Intent.CATEGORY_HOME);
i1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
i1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i1);
finish();

6
为什么要两次FLAG_ACTIVITY_CLEAR_TASK
Choletski 2015年

1
据我了解,.setFlags替换了以前的标志,并且不追加任何标志。.addFlags是我想使用的吗?导致i1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)以上的所有代码;被淘汰
iOSAndroidWindowsWindowsMo​​bileAppsDev 2016年

addFlags为我工作
Jamil

1
setFlags将替换所有先前的,所以last setFlags仅有效,先前被替换。因此,您无需致电i1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); i1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
mtrakal '18

8

我有可以使用的相同问题IntentCompat,例如:

import android.support.v4.content.IntentCompat;
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);

这段代码对我有用。

Android API 17


8

就我而言,我finishAffinity()在上一个活动中使用了功能,例如:

finishAffinity()
startHomeActivity()

希望它会有用。



6

登录->主页->屏幕1->屏幕2->屏幕3->屏幕4->屏幕5

在屏幕4(或其他任何屏幕)上->

StartActivity(登录)
FLAG_ACTIVITY_CLEAR_TOP


2
当我按下后退按钮时,所有先前的活动都按照它们被关闭的顺序显示。那些活动需要关闭,当单击注销按钮时,堆栈中将只有一个活动,这将是登录活动。登录屏幕。用户从主屏幕启动。
Tanmay Mandal

6

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

详细说明您的答案,以便每个人都可以从中受益。
Shubhamoy

5

如果您startActivityForResult()在以前的活动中使用过,只需在所有活动中覆盖OnActivityResult()并调用其中的finish();方法即可。


不,我startActivity只用。
Tanmay Mandal

onActivityResult每次活动都很难维护。我实现了DArkO的建议,实现了我的目标,并感谢您的帮助。
Tanmay Mandal

3

当用户单击注销按钮,然后输入以下代码:

Intent intent = new Intent(this, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

而且在登录后,如果您调用新活动,请不要使用finish();


2

简而言之,当您从登录屏幕转到而不是在完成登录屏幕时。

然后在所有转发活动中,使用此命令注销:

final Intent intent = new Intent(getBaseContext(), LoginScreen.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(intent);

它运作完美。


1

如果您登录用户,screen 1然后从那里转到其他屏幕,请使用

Intent intent = new Intent(this, Screen1.class);
intent.addFlags(FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

当我按下后退按钮时,所有先前的活动都按照它们被关闭的顺序显示。那些活动需要关闭,单击注销按钮时,堆栈中将只有一个活动,那就是登录活动。
Tanmay Mandal

如果您想要这种行为,则必须在每个活动中(除了登录活动之外)都覆盖onKeyDownonBackPressed(或者onKeyDown,如果您想支持Android版本<2.0),则必须覆盖和(startActivity(login)如上所示)。
加布里埃尔·内古特2011年

我有一个按钮,它将带我进入登录屏幕以完成堆栈中的所有活动。
Tanmay Mandal

1

我发现这样,它将清除所有历史记录并退出

Intent startMain = new Intent(Intent.ACTION_MAIN);
startMain.addCategory(Intent.CATEGORY_HOME);
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startMain);
Intent intent = new Intent(getApplicationContext(), SplashScreen.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

finish();
System.exit(0);

1

我想我来晚了,但是答案很简单。Activity中有一个finishAffinity()方法可以完成当前活动和所有父活动,但仅在Android 4.1或更高版本中有效。

对于API 16+,请使用

finishAffinity();

16岁以下使用

ActivityCompat.finishAffinity(YourActivity.this);

希望能帮助到你!

shareedit回答了18年5月27日在8:03

Akshay Taru


0

我发现此解决方案可以在所有设备上使用,尽管它具有API级别(即使对于<11)

Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
ComponentName cn = intent.getComponent();
Intent mainIntent = IntentCompat.makeRestartActivityTask(cn);
startActivity(mainIntent);


0
startActivity(
                Intent(this, LoginActivity::class.java)
                    .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                    .addFlags(FLAG_ACTIVITY_CLEAR_TASK)
            )
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.