清除整个历史堆栈并在Android上开始新的活动

是否有可能在堆栈上开始一个活动,清除之前的整个历史?

情况

我有一个活动堆栈,要么A-→B-> C或B-> C(屏幕Aselect用户令牌,但许多用户只有一个令牌)。

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

笔记

还有很多其他类似的问题,但我还没有find任何答案,这个确切的问题。 我尝试调用getParent().finish() – 这总是导致空指针exception。 FLAG_ACTIVITY_CLEAR_TOP只在活动已经在堆栈上时才起作用。

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

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

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

不幸的是API lvl <= 10,我还没有find一个干净的解决scheme。 “DontHackAndroidLikeThis”解决scheme的确是纯粹的hackery。 你不应该这样做。 🙂

编辑:根据@ 本皮尔逊的评论,对于API <= 10现在可以使用相同的IntentCompat类。 可以使用IntentCompat.FLAG_ACTIVITY_CLEAR_TASK标志清除任务。 所以你也可以支持预先的API级别11。

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

这里Activity的stream程是A-> B。在B上单击Backbutton,我们需要closures应用程序,然后从A开始Activity B,只需调用finish(),这将防止android将Activity A存储到Backstack.eg中。应用程序的Loding / Splash屏幕。

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

案例2:两项以上活动:

如果出现类似于A-> B-> C-> D-> B的stream程,并且在Activity D中单击了Activity B中的Backbutton,那么我们应该使用这个stream程。

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

这里Activity B将从Backstack而不是一个新实例启动,因为Intent.FLAG_ACTIVITY_CLEAR_TOP和Intent.FLAG_ACTIVITY_NEW_TASK会清除堆栈并使其成为第一个。所以当我们按回来button时,整个应用程序将被终止。

我也花了几个小时…并同意FLAG_ACTIVITY_CLEAR_TOP听起来像你想要的:清除整个栈,除了正在启动的活动,所以后退button退出应用程序。 然而,正如Mike Repass所提到的,FLAG_ACTIVITY_CLEAR_TOP只有在您正在启动的活动已经在堆栈中时才会起作用。 当活动不在那里,旗子什么都不做。

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

现在,当FLAG_ACTIVITY_CLEAR_TOP去查找堆栈中的新活动时,它将会在那里被清除之前被拉起。

这是我的注销function; View参数是函数所附的button。

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

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

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

  • 通过将其添加到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(); } 

并处理后退button从堆栈pop()

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

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

方法适合> = API 16。

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

紧接着你开始一个新的活动,使用startActivity ,确保你调用finish()以便当前的活动不会堆积在新的活动之后。

尝试这个:

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

我发现太简单了,只需要在AndroidManifest添加新元素:

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

android:noHistory会从Stack中清除不需要的活动。

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