Android:从后台堆栈中删除所有以前的活动
Posted
技术标签:
【中文标题】Android:从后台堆栈中删除所有以前的活动【英文标题】:Android: Remove all the previous activities from the back stack 【发布时间】:2012-10-08 12:19:39 【问题描述】:当我点击 Profile 活动中的 Logout 按钮时,我想将用户带到 Login 页面,他需要使用新的凭据。
因此我使用了这个代码:
Intent intent = new Intent(ProfileActivity.this,
LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
在注销按钮的onButtonClick
中。
但问题是当我单击登录活动上的设备后退按钮时,它会将我带到 ProfileActivity。当我按下 LoginActivity 上的设备后退按钮时,我期待应用程序应该关闭。
我做错了什么?
我还在清单中为我的 LoginActivity
添加了android:launchMode="singleTop"
谢谢
【问题讨论】:
@GauravVashisth 我只是在关注这个解决方案***.com/questions/5794506/… @abbas.aniefa 这个解决方案我有点复杂。这是清除所有后台堆栈的唯一方法。因为我有 30 多个活动,所以我应该为所有活动编写此广播代码 那就试试这个吧,***.com/questions/10961481/…。使用广播是更好的解决方案。 另一种可用于注销的方法,一旦您注销将一个标志存储在 sharedpreferences 和活动的每个 onRestart() 方法中,您可以检查此变量值,如果它设置为 true,您可以完成当前活动。所以无论有多少活动在后台打开。这将完成您的所有活动。 您的原始代码通过调整实际上适用于 API 级别 11 或更高级别。您只需在一次调用中将标志放在一起:intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
我从这个问题中得到了答案:***.com/questions/3473168/…
【参考方案1】:
here 提出的解决方案对我有用:
Java
Intent i = new Intent(OldActivity.this, NewActivity.class);
// set the new task and clear flags
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);
科特林
val i = Intent(this, NewActivity::class.java)
// set the new task and clear flags
i.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
startActivity(i)
但是,它需要 API 级别 >= 11。
【讨论】:
各位,阅读FLAG_ACTIVITY_CLEAR_TASK
的文档。这是官方的获取方式。无需更改应用中的所有活动。
这不适用于通知***.com/questions/24873131/…
我的 minAPI = 16,所以这对我来说非常好。但是,我注意到 API >21 时视图执行有点迟缓,而 API
这将为活动创建一个新任务
@kgiannakakis 如果我们只有一个任务(活动返回堆栈),毫无疑问解决方案是有效的,但是当我们有多个任务(活动堆栈)时,它就不起作用了。例如,假设我的应用程序 A、B、C 和 D 有四个活动。假设我有两个活动回栈 A->B->C(background) & D->A->B(Foreground),如果我使用意图过滤器从我当前的堆栈(D->A->B)调用活动A 你建议会发生什么它清除我当前的堆栈(D->A->B)并打开活动A,当我按下它时关闭应用程序,但如果我按下最近的应用程序按钮,我可以在那里看到我的应用程序的两个后堆栈。【参考方案2】:
这是在您使用注销按钮时清除所有应用程序活动的一种解决方案。
每次启动 Activity 时,都这样启动:
Intent myIntent = new Intent(getBaseContext(), YourNewActivity.class);
startActivityForResult(myIntent, 0);
当您想关闭整个应用程序时,请执行以下操作:
setResult(RESULT_CLOSE_ALL);
finish();
RESULT_CLOSE_ALL 是一个最终的全局变量,带有一个唯一整数,表示您要关闭所有活动。
然后定义每个活动的onActivityResult(...)
回调,这样当活动返回RESULT_CLOSE_ALL 值时,它也会调用finish()
:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
switch(resultCode)
case RESULT_CLOSE_ALL:
setResult(RESULT_CLOSE_ALL);
finish();
super.onActivityResult(requestCode, resultCode, data);
这将导致关闭所有活动的级联效应。
然而,这是一个 hack,它使用 startActivityForResult
的方式并非设计用于使用。
也许更好的方法是使用广播接收器,如下所示:
On logout, clear Activity history stack, preventing "back" button from opening logged-in-only Activites
其他方法也可以查看这些线程:
Android: Clear the back stack
Finish all previous activities
【讨论】:
历史上有大约 30 个活动是否可行? 应该是。但是,如果您在历史上有 30 个活动,那么您可能需要考虑更改您的设计。 30 似乎有点太多了,Android 可能会自己杀死它们。 这似乎是一种糟糕的做法。 @RakeshGondaliya 的回答问题似乎是合法的。 30 可能只是一个代表“高”活动数量的数字。这个答案看起来更好:***.com/a/3008684/243709 这个答案很棒。您还可以使用 EventBus 库将事件发送到 backstack 中的活动。 github.com/greenrobot/EventBus 最好使用简单的“Intent.FLAG_ACTIVITY_CLEAR_TOP”标志【参考方案3】:要完全清除活动堆栈,您需要使用 TaskStackBuilder 创建一个新的任务堆栈,例如:
Intent loginIntent = LoginActivity.getIntent(context);
TaskStackBuilder.create(context).addNextIntentWithParentStack(loginIntent).startActivities();
这不仅会创建一个新的、干净的任务堆栈,而且如果您的 LoginActivity 有父 Activity,它还将允许“向上”按钮正常运行。
【讨论】:
这是最好的方法。FLAG_ACTIVITY_NEW_TASK
或 finishAffinity()
对我不起作用。只有这个答案解决了目的。
如果我通过后退按钮离开应用程序并通过应用程序图标返回,它会在我调用该方法的活动中打开。所以不适合我。【参考方案4】:
在 API 16 中添加了finishAffinity()
。在以前的版本中使用ActivityCompat.finishAffinity()
。当您将使用意图启动任何活动并完成当前活动时。现在使用ActivityCompat.finishAffinity()
代替finish()
。它将完成当前活动下方的所有堆叠活动。对我来说效果很好。
【讨论】:
其实是ActivityCompat.finishAffinity()
finishAffinity()
也完成了当前活动,所有活动都存在于具有相同亲和力的后堆栈中。【参考方案5】:
什么对我有用
Intent intent = new Intent(getApplicationContext(), HomeActivity.class);
ComponentName cn = intent.getComponent();
Intent mainIntent = IntentCompat.makeRestartActivityTask(cn);
startActivity(mainIntent);
【讨论】:
【参考方案6】:对于 API 11+,您可以像这样使用 Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK
:
Intent intent = new Intent(this, MyActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
它将完全清除所有以前的活动并开始新的活动。
【讨论】:
【参考方案7】:你可以试试finishAffinity()
,它会关闭所有当前的活动并在Android 4.1及以上版本上运行
【讨论】:
finishAffinity() 在 API 16 中添加。在以前的版本中使用 ActivityCompat.finishAffinity()。我工作得很好。【参考方案8】:我可以建议您的一个可能的解决方案是在我的 ProfileActivity 的清单中添加 android:launchMode="singleTop"
。当点击注销时,您可以注销 重新开始LoginActivity。
注销时你可以调用它。
Intent in = new Intent(Profile.this,Login.class);
in.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(in);
finish();
【讨论】:
我这样做了,发生的事情是:当我单击返回按钮时,它会将我带到我来到 ProfileActivity 的 Activity 这可能是因为您通过调用新意图而不是通过调用完成()来访问 ProfileActivity;除了 LoginActivty 之外,您是如何从其他活动进入 ProfileActivity 的? 我遇到了同样的问题。我认为当登录意图被系统破坏时它不起作用,比如由于缺少内存。【参考方案9】:使用以下activity
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
移除 CLEAR_TASK 标记以供片段使用。
我希望这对某些人有用。
【讨论】:
附加说明“删除 CLEAR_TASK 标志以供片段使用”救了我。你是一个伟大的灵魂!感谢您终止我的 2 小时连续调试;)【参考方案10】:我也面临同样的问题..
在登录活动中我所做的是。
Intent myIntent = new Intent(MainActivity.this, ActivityLoggedIn.class);
finish();
MainActivity.this.startActivity(myIntent);
退出时
Intent myIntent = new Intent(ActivityLoggedIn.this, MainActivity.class);
finish();
ActivityLoggedIn.this.startActivity(myIntent);
这很好,但是当我在 ActivityLoggedIn 中并且我最小化应用程序并单击应用程序抽屉上的启动器按钮图标时,MainActivity 再次启动:-/我正在使用标志
android:LaunchMode:singleTask
用于 MainActivity。
【讨论】:
【参考方案11】:没有一个意图标志对我有用,但这是我修复它的方法:
当用户从一个活动中退出时,我必须从该活动中广播一条消息,然后在我想关闭的活动中接收它,然后我调用 finish();而且效果很好。
【讨论】:
【参考方案12】:坚持
Intent intent = new Intent(ProfileActivity.this,
LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
【讨论】:
它不工作。我仍然可以使用后退按钮转到 ProfileActivity【参考方案13】:试试这个,它会起作用的:
Intent logout_intent = new Intent(DashboardActivity.this, LoginActivity.class);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(logout_intent);
finish();
【讨论】:
【参考方案14】:在 API 级别 11 或更高版本中,在 Intent 上使用 FLAG_ACTIVITY_CLEAR_TASK
和 FLAG_ACTIVITY_NEW_TASK
标志来清除所有活动堆栈。
Intent i = new Intent(OldActivity.this, NewActivity.class);
// set the new task and clear flags
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(i);
【讨论】:
【参考方案15】:高级、可重用的 Kotlin:
您可以直接使用 setter 方法设置标志。在 Kotlin 中,or
是 Java 按位的 replacement 或 |
。
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
如果你打算经常使用这个,创建一个 Intent 扩展函数
fun Intent.clearStack()
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
然后您可以在启动意图之前直接调用此函数
intent.clearStack()
如果您需要在其他情况下添加附加标志的选项,请在扩展函数中添加一个可选参数。
fun Intent.clearStack(additionalFlags: Int = 0)
flags = additionalFlags or Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
【讨论】:
【参考方案16】:为您的活动添加到清单android:launchMode="singleTask"
【讨论】:
【参考方案17】:你可以使用下面的方法
fun signOut(context: Context)
try
val intent = Intent(context, SplashActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
context.startActivity(intent)
(context as Activity).finishAffinity()
catch (e: Exception)
LogUtils.logE("EXCEPTION", e)
【讨论】:
【参考方案18】:使用这个
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();
【讨论】:
你知道 setFlags 和 addFlags 吗?以上是关于Android:从后台堆栈中删除所有以前的活动的主要内容,如果未能解决你的问题,请参考以下文章