清除整个历史堆栈并在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。