2010-08-13 116 views
245

是否可以在堆栈上启动一个活动,并清除整个历史记录?清除整个历史堆栈并在Android上启动新的活动

的情况

我有一个活动堆栈,要么去A-> B-> C或B-> C(画面A选择的用户令牌,但许多用户只具有单一的令牌)。

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

注意

还有许多其他类似的问题,但我还没有发现任何回答就这个问题询问。我试着调用getParent().finish() - 这总是导致空指针异常。 FLAG_ACTIVITY_CLEAR_TOP只适用于活动已经在堆栈上。

回答

507

在API级别11新旗意向加入只是这样:Intent.FLAG_ACTIVITY_CLEAR_TASK

只是为了澄清,使用此:

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 

不幸的是API lvl < = 10,我还没有找到一个干净的解决方案。 "DontHackAndroidLikeThis" solution确实是纯粹的hackery。你不应该那样做。:)

编辑: 按@Ben Pearson的评论,对API < = 10现在可以使用IntentCompat类相同。可以使用IntentCompat.FLAG_ACTIVITY_CLEAR_TASK标志清除任务。所以你也可以支持pre API级别11。

+21

我想弄清楚,使用:intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); – user123321 2012-03-12 18:18:27

+2

没有Intent.FLAG_ACTIVITY_NEW_TASK应用程序有时只是关闭本身在Android 4 – max4ever 2012-10-12 15:00:16

+20

IntentCompat有一个标志,现在明确任务为好,这样你就可以支持预API级别11 - http://developer.android.com/reference/android/支持/ V4 /内容/ IntentCompat.html#FLAG_ACTIVITY_CLEAR_TASK – 2013-12-12 12:34:38

11

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

我可以想办法做到这一点,但它是相当黑客。

  • 通过将其添加到AndroidManifest 实例让你的活动singleTask

    <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"/> 
    
  • 扩展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); 
    } 
} 

从A到B:

DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication(); 
app.addBackActivity(A.class); 
startActivity(this, B.class); 

从B到C:

DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication(); 
app.addBackActivity(B.class); 
startActivity(this, C.class); 

在C:

If (shouldNotGoBackToB()) { 
    DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication(); 
    app.pop(); 
} 

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

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

+0

最后,我决定离开堆栈完好无损,只是告诉他们当前的屏幕是无效的用户 – Casebash 2010-08-16 01:42:00

+1

很沮丧的是Android不就让我们已经管理活动堆栈这种方式。我很想在未来的android应用中使用这个解决方案。 – Cephron 2013-02-19 16:14:21

+4

只是为了清楚为什么不应该使用它:这是一个创建内存泄漏的好方法。在某些时候,操作系统可能会决定终止后台活动,但是由于“应用程序”采用了它们的实例,操作系统将无法从被销毁的活动中释放该RAM。 – 2013-11-12 12:57:57

8

在开始新活动后,立即使用startActivity,确保您拨打finish(),以便当前活动不会叠加在新活动后面。

+0

+1很好的解决方案,可以防止特定情况下的某个活动被放置到历史堆栈中。 – marsbear 2012-04-27 09:38:33

+24

如果你有在堆栈中的终点只会清除以前的活动,但没有其他人.... – Necronet 2012-08-13 12:20:46

32

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

这里活动流程是A-> B。对单击后退按钮的B,我们需要关闭该应用程序,然后同时从A只是调用完成启动活动B ()这会阻止android将Activity A存储到Backstack.eg中,因为Activity A是应用程序的Loding/Splash屏幕。

Intent newIntent = new Intent(A.this, B.class); 
startActivity(newIntent); 
finish(); 

情况2:两个以上activitiy:

如果像A-> B-> C-> D-流> B和上点击返回按钮活动B而到来来自活动D.在这种情况下,我们应该使用。

Intent newIntent = new Intent(D.this,B.class); 
newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
startActivity(newIntent); 

这里活动B将从堆栈中开始,而不是因为Intent.FLAG_ACTIVITY_CLEAR_TOP和Intent.FLAG_ACTIVITY_NEW_TASK的新实例清除栈,并使其顶部one.So当我们按下后退按钮整个应用程序会被终止。

+2

这为我工作不止一项活动是行不通的。我把所有的活动都放在那些旗帜上。在这些活动中,后退按钮完全适用于以前的活动,并且在主要活动中使用 Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_HOME); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); \t \t intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); finish(); 整个应用程序被关闭,仍然在内存中,但没有活动,如果你重新启动应用程序去闪屏:) – Rako 2013-07-19 10:50:56

18

我也在这上面花了几个小时......并同意FLAG_ACTIVITY_CLEAR_TOP听起来像你想要的:清除整个堆栈,除了正在启动的活动外,所以后退按钮退出应用程序。然而,正如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(); 
} 
+0

你的意思是CLEAR_TASK而不是CLEAR_TOP? – 2014-08-19 18:40:22

0

我发现太简单的黑客在AndroidManifest因为只是这样做增加新的元素: -

<activity android:name=".activityName" 
      android:label="@string/app_name" 
      android:noHistory="true"/> 

android:noHistory将清除栈你希望活动。

+0

如果您在此活动中要求提供授权,此解决方案可能会导致Android 6.0及更高版本出现问题。 – 2016-09-03 10:34:03

13

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

方法适合> = API 16。

Intent mIntent = new Intent(mContext,MainActivity.class); 
finishAffinity(); 
startActivity(mIntent); 
  • 它是一样开始新的活动,并清除所有堆栈。
  • 或重新启动到MainActivity/FirstActivity。
+1

这样做的窍门,标志werent工作在4.x.x为我,这完美的工作!谢谢 – 2016-09-23 18:57:21

-1

有时你的android模拟器可能无法连接eclipse DDMS工具并要求adb手动启动。在这种情况下,您可以使用命令提示符启动或停止adb。

+1

有时你的android模拟器可能无法连接eclipse DDMS工具并要求adb手动启动。在这种情况下,您可以使用命令提示符启动或停止adb。 Intent i = new Intent(OldActivity.this,NewActivity.class); //设置新任务并清除标志 i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK) startActivity(i); – RajeshkumarG 2016-10-06 09:11:20

2

尝试这种情况:

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

意图I =新意图(MainPoliticalLogin.this,MainActivity.class); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

     startActivity(i); 
相关问题