ChatGPT解决这个技术问题 Extra ChatGPT

完成之前的所有活动

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

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 运行嵌套活动?
没有。所有的活动都是用startActivity启动的。
我正在使用嵌套活动,而 cod 在嵌套活动中运行 finishaffinitytask()。它会改变行为吗?因为有时我在finishaffinitytask运行时交付结果ResultInfo失败。
请检查这个答案,它一定会帮助你stackoverflow.com/a/25159180/2732632
Android 21 引入了 Activity.finishAndRemoveTask()。

A
Anye

利用:

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

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

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

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


用户将他的第一个屏幕显示为主屏幕,这是主要问题。
以及我有我的回应你需要回到主屏幕并完成那个。因此该过程从任何屏幕调用上述意图。在主屏幕上接收意图并在 startActivity 方法之后立即启动登录意图并完成主页。您还可以将待处理的动画覆盖为空输入和输出,这样它就不会显示过渡(我这样做是因为它感觉有点快)。所以对于您需要的东西应该可以正常工作。
与其将 Activity 声明为 singleInstance,不如考虑使用 FLAG_ACTIVITY_CLEAR_TOP|FLAG_ACTIVITY_SINGLE_TOP 作为 Intent 的标志。这将完成干预活动并开始(或回到前台)所需的活动。
@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);
此代码仅清除顶部活动堆栈,用于清除所有活动 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
t
tbraun89

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


正确的解决方案,但只有 API 11+
我最终使用了这个额外的标志,因为它在显示主要活动时不会导致延迟(它不会重新启动它,所以它更快)。
@riwnodennyk 为什么 API 11+?
对 11 之前的版本使用 IntentCompat.FLAG_ACTIVITY_CLEAR_TASK
@ono 是的。这应该就是你所需要的。确保您的目标活动的启动模式在清单中设置为“singleTask”。
H
Henrique

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

finishAffinity();

或者,如果您希望它在以前的 Android 版本中工作:

ActivityCompat.finishAffinity(this);

ActivityCompat.finishAffinity(this);为 api < 16 调用 activity.finish()。所以它不起作用。
@Beto Caldas,我自己确认了源代码,它不适用于 AamirAbro 提到的 API < 16。它只会完成您在 API < 16 上传递的活动。
P
Peter Mortensen

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

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

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

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

为什么在 Android 中制作退出按钮如此困难?

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

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

当用户恢复您的应用程序时,他们会从上次中断的地方继续,不会中断。这个退出按钮正在篡夺活动管理器的权力,可能会导致自动管理的 android 程序生命周期出现问题。


A
AkshayT

我想我迟到了,但有一个简单而简短的答案。 Activity中有一个finishAffinity()方法可以完成当前Activity和所有父Activity,但它只适用于Android 4.1或更高版本。

对于 API 16+,请使用

finishAffinity();

对于 16 岁以下,使用

ActivityCompat.finishAffinity(YourActivity.this);

希望能帮助到你!


G
Gem
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
A
Aristo Michael

使用以下活动

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

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

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


C
Community

附带说明,很高兴知道
此答案有效 (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 之间区别的很好的解释,谢谢
K
Kos

developer.android.com

public void finishAffinity () 在 API 级别 16 中添加

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

请注意,此完成不允许您将结果传递给先前的活动,如果您尝试这样做,则会引发异常。


J
Jaydeep purohit

如果您的应用程序具有最低 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


D
Djek-Grif

就我而言,我在最后一个活动中使用 finishAffinity() 函数,例如:

finishAffinity()
startHomeActivity()

希望它会有用。


P
Peter Mortensen

我为此实施了一个解决方案(我想我在某个地方的 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);
}

这通常是一个非常糟糕的主意,尽管它可能会起作用,但它会引入一个可能在未来中断的接触点,并且很难调试。我是根据经验告诉你的:)
A
Amrit

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

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

P
Prashant Kumar
    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);
A
Adnan Abdollah Zaki

我有同样的问题,你可以使用 IntentCompat ,像这样:

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

这段代码对我有用。

安卓 API 17


H
Hitesh Kushwah

而不是使用 finish() 只需使用 finishAffinity();


很好的答案,但需要 API 16
H
Husnain Ali

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

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

StartActivity(Log in)
FLAG_ACTIVITY_CLEAR_TOP


当我按下后退按钮时,所有先前的活动都按它们的顺序显示。这些活动需要关闭,当单击注销按钮时,堆栈中只有一个活动,这将是登录活动。并且没有登录屏幕。用户从主屏幕开始。
K
Kamal Bunkar

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

详细说明您的答案,以便每个人都能从中受益。
P
Peter Mortensen

如果您在以前的活动中使用 startActivityForResult(),只需覆盖 OnActivityResult() 并在所有活动中调用其中的 finish(); 方法。这将完成这项工作......


不,我只使用 startActivity
很难在每个活动上维护 onActivityResult。我已经实施了 DArkO 的建议并实现了我的目标,感谢您的帮助。
n
nikki

当用户单击注销按钮时,请编写以下代码:

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

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


S
Samuel Quiroz

我想我迟到了,但有一个简单而简短的答案。 Activity中有一个finishAffinity()方法可以完成当前Activity和所有父Activity,但它只适用于Android 4.1或更高版本。

对于 API 16+,请使用

完成亲和力();

对于 16 岁以下,使用

ActivityCompat.finishAffinity(YourActivity.this);

希望能帮助到你!

shareedit 于 2018 年 5 月 27 日 8:03 回答

阿克谢·塔鲁


P
Peter Mortensen

简单地说,当您从登录屏幕离开时,而不是在完成登录屏幕时。

然后在所有转发活动中,使用它来注销:

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

它完美地工作。


G
Gabriel Negut

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

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

当我按下后退按钮时,所有先前的活动都按它们的顺序显示。这些活动需要关闭,当单击注销按钮时,堆栈中只有一个活动,这将是登录活动。
如果您想要这种行为,您必须在每个活动(登录活动除外)中覆盖 onKeyDownonBackPressed(或 onKeyDown,如果您想支持 Android 版本 < 2.0),并且 {4 } 如上所示。
我有一个按钮,它将带我进入登录屏幕,完成堆栈中的所有活动。这可能吗?
I
ItamarG3

我找到了这种方式,它将清除所有历史记录并退出

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

p
priyankvex

尽管 API 级别(即使 < 11),我发现此解决方案适用于所有设备

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

S
Shivam Tripathi

关闭所有以前的活动并清除内存的最佳方法

finishAffinity()
System.exit(0);

M
MosesK

我已经尝试了我的标志,但仍然没有工作。我有一个设计非常相似的应用程序,并且在逻辑方面我有一个可能的解决方案。我已经使用共享首选项构建了我的登录和注销。

如果我注销,我的共享首选项中的数据将被销毁/删除。

从我的任何活动(例如 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();
}

M
Mori

在 Kotlin 中这样:

在另一个 Activity(带有一些类)中,在 Imports

var activity:Activity?=null
    get() = field
    set(value) {
        field = value
    }

然后,在 onCreate

activity=this

现在在 MainActivity 中:

activity?.finish()