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

这种情况

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

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

笔记

还有很多类似的问题,但我还没有找到任何答案。我尝试调用getParent().finish() -这总是导致一个空指针异常。FLAG_ACTIVITY_CLEAR_TOP只在活动已经在堆栈上时才有效。


当前回答

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

我能想出一个办法来做这件事,但这太麻烦了。

使你的活动singleTask添加到AndroidManifest 例子: <活动android: name = " .activities.A " android: label = " @string / A_title” android: launchMode = " singleTask " / > <活动android: name = " .activities.B " android: label = " @string / B_title” android: launchMode = " singleTask " / > 扩展应用程序,它将保存到哪里去的逻辑。

例子:

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()的返回按钮。

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

其他回答

在API级别11中添加了一个新的Intent标志:Intent。FLAG_ACTIVITY_CLEAR_TASK

澄清一下,用这个:

Java

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

科特林

intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK

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

编辑: 根据@Ben Pearson的评论,对于API <=10,现在可以使用IntentCompat类。可以使用IntentCompat。FLAG_ACTIVITY_CLEAR_TASK清除任务的标志。所以你也可以支持pre API level 11。

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

我发现太简单的hack只是这样做,在AndroidManifest中添加新元素:-

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

android:noHistory将清除堆栈中不需要的活动。

在爪哇:-

 startActivity(new Intent(getApplicationContext(),ChooseServiceActivity.class)
                        .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));

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

我能想出一个办法来做这件事,但这太麻烦了。

使你的活动singleTask添加到AndroidManifest 例子: <活动android: name = " .activities.A " android: label = " @string / A_title” android: launchMode = " singleTask " / > <活动android: name = " .activities.B " android: label = " @string / B_title” android: launchMode = " singleTask " / > 扩展应用程序,它将保存到哪里去的逻辑。

例子:

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()的返回按钮。

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