完成之前的所有活动
Posted
技术标签:
【中文标题】完成之前的所有活动【英文标题】:Finish all previous activities 【发布时间】:2011-09-13 21:18:54 【问题描述】:我的应用程序有以下流程屏幕:
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
来实现这一点。
我还在***中查看了一些答案,但无法解决问题。
我的应用程序在 android 1.6 上,所以无法使用 FLAG_ACTIVITY_CLEAR_TASK
有什么办法可以解决这个问题吗?
【问题讨论】:
您是否使用 startActivityForResult 运行嵌套活动? no.所有的activity都是用startActivity启动的。 我正在使用嵌套活动,而 cod 在嵌套活动中运行 finishaffinitytask()。它会改变行为吗?因为有时我在finishaffinitytask运行时交付结果ResultInfo失败。 请检查这个答案,它一定会帮助你***.com/a/25159180/2732632 Android 21 引入了 Activity.finishAndRemoveTask()。 【参考方案1】:登录->首页->屏幕1->屏幕2->屏幕3->屏幕4->屏幕5
在屏幕 4(或任何其他)上 ->
StartActivity(Log in)和
FLAG_ACTIVITY_CLEAR_TOP
【讨论】:
当我按下后退按钮时,所有以前的活动都按它们的顺序显示。这些活动需要关闭,当单击注销按钮时,堆栈中只有一个活动,这将是登录活动。并且没有登录屏幕。用户从主屏幕开始。【参考方案2】:如果您在screen 1
中登录用户并从那里转到其他屏幕,请使用
Intent intent = new Intent(this, Screen1.class);
intent.addFlags(FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
【讨论】:
当我按下后退按钮时,所有以前的活动都按它们的顺序显示。这些活动需要关闭,当单击注销按钮时,堆栈中只有一个活动,这将是登录活动。 如果你想要这种行为,你必须在你的每一个活动中覆盖onKeyDown
和onBackPressed
(或者onKeyDown
,如果你想支持startActivity(login)那里如上所示。
我有一个按钮,它将带我进入登录屏幕,完成堆栈中的所有活动。这可能吗?【参考方案3】:
如果您在之前的活动中使用startActivityForResult()
,只需覆盖OnActivityResult()
并在所有活动中调用其中的finish();
方法。这样就可以完成工作...
【讨论】:
不,我只使用startActivity
。
每次活动都很难维护onActivityResult
。我已经实现了DArkO的建议并实现了我的目标,感谢您的帮助。【参考方案4】:
用途:
Intent intent = new Intent(getApplicationContext(), Home.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
这将清除首页上的所有活动。
假设您在用户登录并创建主页时完成登录屏幕,然后在该屏幕之上从 1 到 5 的所有屏幕。我发布的代码将使您返回主屏幕,完成所有其他活动。您可以在 Intent 中添加额外内容,并在主屏幕活动中阅读并完成它(可能从那里再次启动登录屏幕或其他内容)。
我不确定,但您也可以尝试使用此标志登录。我不知道在这种情况下如何安排活动。所以不知道它是否会清除您正在使用的屏幕下方的内容,包括您当前正在使用的内容,但它绝对是要走的路。
希望这会有所帮助。
【讨论】:
用户将他的第一个屏幕显示为主屏幕,这是主要问题。 还有我的回复,您需要返回主屏幕并完成该操作。因此该过程从任何屏幕调用上述意图。在主屏幕上接收意图并在 startActivity 方法之后立即启动登录意图并完成主页。您还可以将待处理的动画覆盖为空,以便输入和输出,这样它就不会显示过渡(我这样做是因为它感觉有点快)。所以对于您需要的东西应该可以正常工作。 与其将活动声明为singleInstance
,不如考虑使用FLAG_ACTIVITY_CLEAR_TOP|FLAG_ACTIVITY_SINGLE_TOP
作为Intent 的标志。这将完成干预活动并开始(或回到前台)所需的活动。
@CommonsWare 将intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);
添加到我的活动对我没有帮助。它没有完成中间活动。当我从登录屏幕按返回时,我可以看到以前的活动。这是我的代码@ 987654325@.
这段代码只清除顶层activity栈,用于清除所有activity intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);【参考方案5】:
我为此实施了一个解决方案(我想我在某个地方的 *** 上找到了它,但我不记得了,所以首先感谢这样做的人):
从您的任何活动中执行以下操作:
// 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);
【讨论】:
这通常是一个非常糟糕的主意,尽管它可能会起作用,但它会引入一个可能在未来中断的接触点,并且很难调试。我是根据经验告诉你的:)【参考方案6】:简单地说,当您从登录屏幕离开时,而不是在完成登录屏幕时。
然后在所有转发活动中,使用它进行注销:
final Intent intent = new Intent(getBaseContext(), LoginScreen.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(intent);
效果很好。
【讨论】:
【参考方案7】:当用户点击注销按钮时,编写以下代码:
Intent intent = new Intent(this, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
如果你在登录后调用新活动,也不要使用finish();
【讨论】:
【参考方案8】:当用户希望退出所有打开的活动时,他们应该按下一个按钮来加载应用程序启动时运行的第一个活动,清除所有其他活动,然后完成最后一个剩余活动.当用户按下退出按钮时,运行以下代码。就我而言,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
并传递了'EXIT' 信号:
if (getIntent().getBooleanExtra("EXIT", false))
finish();
为什么在 Android 中制作退出按钮如此困难?
Android 极力劝阻您不要在应用程序中使用“退出”按钮,因为他们希望用户永远不会关心他们使用的程序是否在后台运行。
Android 操作系统开发人员希望您的程序能够在手机意外关机和断电的情况下幸存下来,并且当用户重新启动程序时,他们会从上次中断的地方继续。因此,用户可以在使用您的应用程序时接听电话,并打开需要释放您的应用程序以获取更多资源的地图。
当用户继续您的应用程序时,他们会从上次中断的地方继续,不会中断。这个退出按钮正在篡夺活动管理器的权力,可能会导致自动管理的 android 程序生命周期出现问题。
【讨论】:
【参考方案9】:你可以试试Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK
。它将完全清除所有以前的活动并开始新的活动。
【讨论】:
正确的解决方案,但仅限 API 11+ 我最终使用了这个额外的标志,因为它在显示主要活动时不会导致延迟(它不会重新启动它,所以它更快)。 @riwnodennyk 为什么 API 11+? 在 11 之前的版本中使用 IntentCompat.FLAG_ACTIVITY_CLEAR_TASK @ono 是的。这应该就是你所需要的。确保您的目标 Activity 的启动模式在清单中设置为“singleTask”。【参考方案10】:来自developer.android.com:
public void finishAffinity ()
在 API 级别 16 中添加
在当前任务中完成此活动以及紧接其下方的所有具有相同亲和力的活动。这通常在应用程序可以启动到另一个任务时使用(例如从它理解的内容类型的 ACTION_VIEW)并且用户已经使用向上导航切换出当前任务并进入它自己的任务。在这种情况下,如果用户向下导航到第二个应用程序的任何其他活动,则所有这些活动都应作为任务切换的一部分从原始任务中删除。
请注意,此完成不允许您将结果传递给上一个活动,如果您尝试这样做,则会引发异常。
【讨论】:
【参考方案11】:对于应用程序最后一个屏幕上的注销按钮,在注销按钮侦听器上使用此代码完成所有打开的先前活动,您的问题就解决了。
Intent intent = new Intent(this, loginScreen.class);
ntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
【讨论】:
【参考方案12】: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
。【参考方案13】:
在启动新 Activity 之前,只需添加以下代码:
finishAffinity();
或者,如果您希望它在以前的 Android 版本中运行:
ActivityCompat.finishAffinity(this);
【讨论】:
ActivityCompat.finishAffinity(this);为 api @Beto Caldas,我自己确认了源代码,它不适用于 AamirAbro 提到的 API 【参考方案14】:使用以下内容进行活动
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
删除 CLEAR_TASK 标志以供片段使用。
我希望这对某些人有用。
【讨论】:
【参考方案15】:我有同样的问题
你可以使用IntentCompat
,像这样:
import android.support.v4.content.IntentCompat;
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
这段代码对我有用。
Android api 17
【讨论】:
【参考方案16】: 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();
【讨论】:
为什么FLAG_ACTIVITY_CLEAR_TASK两次? 据我了解, .setFlags 替换了以前的标志并且不附加任何标志。 .addFlags 是你想用的我猜?导致上面的所有代码 i1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);被消灭了 addFlags 对我有用setFlags
会替换所有之前的,所以最后的setFlags
是唯一有效的,之前的会被替换。所以你不需要打电话给i1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); i1.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
【参考方案17】:
我发现此解决方案适用于所有设备,尽管 API 级别(即使对于
Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
ComponentName cn = intent.getComponent();
Intent mainIntent = IntentCompat.makeRestartActivityTask(cn);
startActivity(mainIntent);
【讨论】:
【参考方案18】:如果您的应用程序具有最低 sdk 版本 16,那么您可以使用 finishAffinity()
在当前任务中完成此活动以及紧接其下方的所有具有相同亲和力的活动。
这对我有用 在 Top Payment 屏幕中删除所有后台活动,
@Override
public void onBackPressed()
finishAffinity();
startActivity(new Intent(PaymentDoneActivity.this,Home.class));
http://developer.android.com/reference/android/app/Activity.html#finishAffinity%28%29
【讨论】:
【参考方案19】:对于 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);
【讨论】:
详细说明你的答案,让每个人都能从中受益。【参考方案20】:我找到了这个方法,它会清除所有历史并退出
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);
【讨论】:
【参考方案21】:顺便说一句,很高兴知道 这个答案有效(https://***.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 的区别,谢谢【参考方案22】:不要使用finish()
,而是使用finishAffinity();
【讨论】:
好答案,但需要 API 16【参考方案23】:我想我迟到了,但有一个简单而简短的答案。 Activity中有一个finishAffinity()方法可以完成当前Activity和所有父Activity,但它只适用于Android 4.1或更高版本。
对于 API 16+,使用
finishAffinity();
16岁以下,使用
ActivityCompat.finishAffinity(YourActivity.this);
希望对你有帮助!
【讨论】:
【参考方案24】:就我而言,我在最后一个活动中使用finishAffinity()
函数,例如:
finishAffinity()
startHomeActivity()
希望对你有用。
【讨论】:
【参考方案25】:关闭之前所有活动并清除内存的最佳方式
finishAffinity()
System.exit(0);
【讨论】:
【参考方案26】:我想我迟到了,但有一个简单而简短的答案。 Activity中有一个finishAffinity()方法可以完成当前Activity和所有父Activity,但它只适用于Android 4.1或更高版本。
对于 API 16+,使用
finishAffinity();
16岁以下,使用
ActivityCompat.finishAffinity(YourActivity.this);
希望对你有帮助!
分享编辑 2018 年 5 月 27 日 8:03 回答
阿克谢塔鲁
【讨论】:
【参考方案27】:我已经尝试了我的标志,但仍然没有工作。我有一个设计非常相似的应用程序,并且在逻辑方面我有一个可能的解决方案。我已经使用共享首选项构建了登录和注销。
如果我退出,我的共享首选项中的数据将被销毁/删除。
从我的任何活动(例如 Home.java)中,我检查共享首选项是否有数据,在这种情况下它不会,因为我在从其中一个屏幕注销时销毁了它。因此,逻辑会破坏/完成该活动并将我带回登录活动。您可以在所有其他活动中复制此逻辑。
但是请记住在 onPostResume() 中执行此检查,因为这是您返回 Home.java 时调用的内容
代码示例如下:
@Override
protected void onPostResume()
SharedPreferences pref = this.getSharedPreferences("user_details", Context.MODE_PRIVATE);
if (pref.getAll().isEmpty())
//Shared Preferences has no data.
//The data has been deleted
Intent intent = new Intent(getApplicationContext(), Login.class);
startActivity(intent);
finish();
//Finish destroys that activity which in our case is the Home.java
super.onPostResume();
【讨论】:
以上是关于完成之前的所有活动的主要内容,如果未能解决你的问题,请参考以下文章