ChatGPT解决这个技术问题 Extra ChatGPT

Android:从后台堆栈中删除所有以前的活动

当我在我的个人资料活动中单击注销按钮时,我想将用户带到登录页面,他需要在其中使用新凭据。

因此我使用了这段代码:

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 我只是在关注这个解决方案stackoverflow.com/questions/5794506/…
@abbas.aniefa 这个解决方案我有点复杂。这是清除所有后台堆栈的唯一方法。因为我有 30 多个活动,所以我应该为所有活动编写此广播代码
试试这个,stackoverflow.com/questions/10961481/…。使用广播是一个更好的解决方案。
您可以用于注销的另一种方法,一旦您注销将一个标志存储在 sharedpreferences 中,并且在活动的每个 onRestart() 方法中,您可以检查此变量值,如果它设置为 true,您可以完成当前活动。所以无论有多少活动在后台打开。这将完成您的所有活动。
您的原始代码通过调整实际上适用于 API 级别 11 或更高级别。您只需在一次调用中将标志放在一起:intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);我从这个问题中得到了答案:stackoverflow.com/questions/3473168/…

R
Ramesh R

提出的解决方案 here 对我有用:

爪哇

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的文档。这是官方获取方式。无需更改应用程序中的所有活动。
我的 minAPI = 16,所以这对我来说非常好。但是,我注意到 API >21 时视图执行有点迟缓,而 API <21 时则流畅。有人遇到同样的问题吗?
这将为活动创建一个新任务
@kgiannakakis 如果我们只有一个任务(活动返回堆栈),毫无疑问解决方案是有效的,但是当我们有多个任务(活动堆栈)时,它就不起作用了。例如,假设我的应用程序 A、B、C 和 D 有四个活动。假设我有两个活动回栈 A->B->C(background) & D->A->B(Foreground),如果我使用意图过滤器从我当前的堆栈(D->A->B)调用活动A 你建议会发生什么它清除我当前的堆栈(D->A->B)并打开活动A,当我按下它时关闭应用程序,但如果我按下最近的应用程序按钮,我可以在那里看到我的应用程序的两个后堆栈。
C
Community

这是使用注销按钮时清除所有应用程序活动的一种解决方案。

每次启动 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 可能只是一个代表“高”活动数量的数字。这个答案看起来更好:stackoverflow.com/a/3008684/243709
这个答案很棒。您还可以使用 EventBus 库将事件发送到 backstack 中的活动。 github.com/greenrobot/EventBus
最好使用带有意图的简单“Intent.FLAG_ACTIVITY_CLEAR_TOP”标志
M
Matt Accola

要完全清除活动堆栈,您需要使用 TaskStackBuilder 创建一个新的任务堆栈,例如:

Intent loginIntent = LoginActivity.getIntent(context);
TaskStackBuilder.create(context).addNextIntentWithParentStack(loginIntent).startActivities();

这不仅会创建一个新的、干净的任务堆栈,如果您的 LoginActivity 有父活动,它还将允许“向上”按钮正常运行。


这是最好的方法。
FLAG_ACTIVITY_NEW_TASKfinishAffinity() 对我不起作用。只有这个答案解决了目的。
如果我通过后退按钮离开应用程序并通过应用程序图标返回,它会在我调用该方法的活动中打开。所以不为我工作。
N
Neeraj Sewani

在 API 16 中添加了 finishAffinity()。在以前的版本中使用 ActivityCompat.finishAffinity()。当您将使用意图启动任何活动并完成当前活动时。现在使用 ActivityCompat.finishAffinity() 而不是 finish()。它将完成当前活动下方的所有堆叠活动。这对我来说可以。


实际上是 ActivityCompat.finishAffinity()
finishAffinity() 还完成当前活动,所有活动都存在于具有相同亲和性的后堆栈中。
M
Mongi Zaidi

什么对我有用

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

n
ndsmyter

您可以尝试 finishAffinity(),它会关闭所有当前活动并在 Android 4.1 及更高版本上运行


在 API 16 中添加了 finishAffinity()。在以前的版本中使用 ActivityCompat.finishAffinity()。我工作得很好。
A
Android

我可以建议您的一种可能的解决方案是在我的 ProfileActivity 的清单中添加 android:launchMode="singleTop"。当点击注销时,您可以注销 重新开始LoginActivity。在注销时您可以调用它。

Intent in = new Intent(Profile.this,Login.class);
                in.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(in);
                finish();

我这样做了,发生的事情是:当我单击后退按钮时,它会将我带到我来到 ProfileActivity 的 Activty
这可能是因为您通过调用新意图而不是通过调用完成()来访问 ProfileActivity;除了 LoginActivty 之外,您是如何从其他活动进入 ProfileActivity 的?
我在问同样的问题。我认为当登录意图被系统破坏时它不起作用,比如由于缺乏内存。
m
madx

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

它将完全清除所有以前的活动并开始新的活动。


G
Gowthaman M

将以下内容用于 activity

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

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

我希望这可能对某些人有用。


附加说明“删除 CLEAR_TASK 标志以供片段使用”救了我。你是一个伟大的灵魂!感谢您终止我 2 小时的连续调试;)
S
Sujal Mandal

我也面临同样的问题。。

在登录活动中,我所做的是。

    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。


I
Ian Wambai

没有一个意图标志对我有用,但这是我修复它的方法:

当用户从一个活动中退出时,我必须从该活动中广播一条消息,然后在我想关闭的活动中接收它,然后我调用 finish();它工作得很好。


G
Gaurav Vashisth

就收下吧

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

它不工作。我仍然可以使用后退按钮转到 ProfileActivity
l
lebelinoz

试试这个它会工作:

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

G
Gowthaman M

在 API 级别 11 或更高版本中,使用 Intent 上的 FLAG_ACTIVITY_CLEAR_TASKFLAG_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);

G
Gibolt

高级、可重用的 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
}

H
Hally Trần

添加到您的活动清单 android:launchMode="singleTask"


R
Ranajit Sawant

您可以使用以下方法

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

    }

G
Gowthaman M

用这个

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 吗?