清除整个历史记录堆栈并在Android上启动新活动

Cas*_*ash 313 android android-activity back-stack

是否可以在堆栈上启动活动,清除之前的整个历史记录?

情况

我有一个活动堆栈,可以是A-> B-> C或B-> C(屏幕A选择用户令牌,但许多用户只有一个令牌).

在屏幕C中,用户可以采取使屏幕B无效的动作,因此应用程序想要将它们带到屏幕A,而不管它是否已经在堆栈中.屏幕A应该是我的应用程序中堆栈上唯一的项目.

笔记

还有许多其他类似的问题,但我没有发现任何可以回答这个问题的问题.我试过调用getParent().finish()- 这总是导致空指针异常.FLAG_ACTIVITY_CLEAR_TOP仅在活动已在堆栈上时才有效.

Ako*_* Cz 627

在API级别11中,为此添加了一个新的Intent Flag:Intent.FLAG_ACTIVITY_CLEAR_TASK

只是为了澄清,使用这个:

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
Run Code Online (Sandbox Code Playgroud)

不幸的是,对于API lvl <= 10,我还没有找到一个干净的解决方案.该"DontHackAndroidLikeThis"的解决方案确实是纯粹的两轮牛车.你不应该这样做.:)

编辑: 根据@Pen Pearson的评论,对于API <= 10,现在可以使用IntentCompat类.可以使用IntentCompat.FLAG_ACTIVITY_CLEAR_TASK标志来清除任务.因此,您也可以支持API级别11.

  • 只是为了澄清,使用:intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); (22认同)
  • IntentCompat现在还有一个标志来清除任务,因此您可以支持pre API级别11 - http://developer.android.com/reference/android/support/v4/content/IntentCompat.html#FLAG_ACTIVITY_CLEAR_TASK (20认同)
  • API级别<10的设备上将忽略IntentCompat.FLAG_ACTIVITY_CLEAR_TASK.http://developer.android.com/reference/android/support/v4/content/IntentCompat.html#FLAG_ACTIVITY_CLEAR_TASK (10认同)
  • IntentCompat的标志只是为了避免崩溃,但不会像@David所说的那样做任何事情. (7认同)
  • 如果没有Intent.FLAG_ACTIVITY_NEW_TASK,应用程序有时会在android 4上自行关闭 (2认同)

小智 48

案例1:只有两个活动A和B:

这里的活动流程是A-> B.点击B的后退按钮我们需要关闭应用程序然后从A启动Activity B只调用finish()这将阻止android将Activity A存储到Backstack.eg中,活动A是Loding/Splash应用程序屏幕.

Intent newIntent = new Intent(A.this, B.class);
startActivity(newIntent);
finish();
Run Code Online (Sandbox Code Playgroud)

案例2:两个以上的活动:

如果有来自活动D的A-> B-> C-> D-> B之类的流程以及活动B中的单击后退按钮.在这种情况下我们应该使用.

Intent newIntent = new Intent(D.this,B.class);
newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(newIntent);
Run Code Online (Sandbox Code Playgroud)

这里活动B将从backstack而不是新实例启动,因为Intent.FLAG_ACTIVITY_CLEAR_TOP和Intent.FLAG_ACTIVITY_NEW_TASK清除堆栈并使其成为最重要的一个.所以当我们按下后退按钮时,整个应用程序将被终止.

  • 这对我有用.我把那些旗帜放进了所有活动中.在那些活动中,后退按钮完美地运行到前一个活动,并且在主要活动中使用Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_HOME); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(意向); 完(); 整个应用程序关闭,仍在内存中但没有活动,如果你重新启动应用程序进入启动画面:) (2认同)

kar*_*ran 35

使用Android的新版本> = API 16使用 finishAffinity()

方法适用于> = API 16.

Intent mIntent = new Intent(mContext,MainActivity.class);
finishAffinity();
startActivity(mIntent);
Run Code Online (Sandbox Code Playgroud)
  • 它与启动新Activity相同,并清除所有堆栈.
  • 或重新启动到MainActivity/FirstActivity.


小智 21

我也花了几个小时...同意FLAG_ACTIVITY_CLEAR_TOP听起来像你想要的:清除整个堆栈,除了正在启动的活动,所以Back按钮退出应用程序.然而正如Mike Repass所提到的,FLAG_ACTIVITY_CLEAR_TOP仅在你正在启动的活动已经在堆栈中时起作用; 当活动不存在时,旗帜不做任何事情.

该怎么办?使用FLAG_ACTIVITY_NEW_TASK将正在启动的活动放入堆栈,这使得该活动成为历史堆栈上新任务的开始.然后添加FLAG_ACTIVITY_CLEAR_TOP标志.

现在,当FLAG_ACTIVITY_CLEAR_TOP用于在堆栈中查找新活动时,它将存在并在其他所有清除之前被拉起.

这是我的退出功能; View参数是函数附加的按钮.

public void onLogoutClick(final View view) {
    Intent i = new Intent(this, Splash.class);
    i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    startActivity(i);
    finish();
}
Run Code Online (Sandbox Code Playgroud)


Mac*_*rse 12

你不应该改变堆栈.Android后退按钮应该像在Web浏览器中一样工作.

我可以想办法做到这一点,但这是一个非常黑客.

  • singleTask通过将其添加到AndroidManifest 示例来进行活动:

    <activity android:name=".activities.A"
              android:label="@string/A_title"
              android:launchMode="singleTask"/>
    
    <activity android:name=".activities.B"
              android:label="@string/B_title"
              android:launchMode="singleTask"/>
    
    Run Code Online (Sandbox Code Playgroud)
  • 延伸Application将保留去哪里的逻辑.

例:

public class DontHackAndroidLikeThis extends Application {

  private Stack<Activity> classes = new Stack<Activity>();

  public Activity getBackActivity() {
    return classes.pop();
  }

  public void addBackActivity(Activity activity) {
    classes.push(activity);
  }
}
Run Code Online (Sandbox Code Playgroud)

从A到B:

DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication();
app.addBackActivity(A.class); 
startActivity(this, B.class);
Run Code Online (Sandbox Code Playgroud)

从B到C:

DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication();
app.addBackActivity(B.class); 
startActivity(this, C.class);
Run Code Online (Sandbox Code Playgroud)

在C:

If ( shouldNotGoBackToB() ) {
  DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication();
  app.pop();
}
Run Code Online (Sandbox Code Playgroud)

pop()从堆栈处理后退按钮.

再一次,你不应该这样做:)

  • 只是要清楚为什么不应该使用它:这是一种创建内存泄漏的好方法.在某些时候,操作系统可能会决定杀死后台活动,但由于`Application`占用了他们的实例,操作系统将无法从被破坏的活动中释放出RAM. (4认同)

Kei*_*ino 11

在您开始新活动之后,请立即使用startActivity,确保拨打电话,finish()以便当前活动不会堆叠在新活动后面.

  • 如果你在堆栈中有多个活动,那么完成将只清除之前的活动而不是其他活动.... (27认同)

Gib*_*olt 6

高级可重用 Kotlin:

您可以使用 setter 方法直接设置标志。在科特林or更换为Java按位或|

intent.flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK
Run Code Online (Sandbox Code Playgroud)

如果你打算经常使用这个,创建一个 Intent 扩展函数

fun Intent.clearStack() {
    flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
Run Code Online (Sandbox Code Playgroud)

然后你可以在开始意图之前直接调用这个函数

intent.clearStack()
Run Code Online (Sandbox Code Playgroud)

如果您需要在其他情况下添加额外标志的选项,请向扩展函数添加一个可选参数。

fun Intent.clearStack(additionalFlags: Int = 0) {
    flags = additionalFlags or Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
Run Code Online (Sandbox Code Playgroud)


小智 5

尝试这个:

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();
Run Code Online (Sandbox Code Playgroud)


小智 5

试试下面的代码,

Intent intent = new Intent(ManageProfileActivity.this, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|
                Intent.FLAG_ACTIVITY_CLEAR_TASK| 
                Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Run Code Online (Sandbox Code Playgroud)


Ami*_*emi 5

对我来说,以上方法都不起作用

只需执行以下操作即可清除所有先前的活动

finishAffinity() // if you are in fragment use activity.finishAffinity()
Intent intent = new Intent(this, DestActivity.class); // with all flags you want
startActivity(intent)
Run Code Online (Sandbox Code Playgroud)