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

时间:2010-08-13 00:59:58

标签: android android-activity back-stack

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

情况

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

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

备注

还有许多其他类似的问题,但我没有找到任何可以解答这个确切问题的问题。我试着调用getParent().finish() - 这总是会导致空指针异常。 FLAG_ACTIVITY_CLEAR_TOP仅在活动已在堆栈中时才有效。

13 个答案:

答案 0 :(得分:597)

在API级别11中,为此添加了一个新的Intent Flag: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标志来清除任务。因此,您也可以支持API级别11。

答案 1 :(得分:45)

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

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

如果存在类似A-> B-> C-> D-> B的流以及来自活动D的活动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);

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

答案 2 :(得分:33)

使用Android的新版本> = API 16使用Intent mIntent = new Intent(mContext,MainActivity.class); finishAffinity(); startActivity(mIntent);

方法适用于> = API 16。

 private class ConnectThread extends Thread {
    private  BluetoothSocket mmSocket;
    private final BluetoothDevice device;

    public ConnectThread(BluetoothDevice device) {
        // Use a temporary object that is later assigned to mmSocket,
        // because mmSocket is final
        BluetoothSocket tmp = null;
        this.device = device;
    }
        // Get a BluetoothSocket to connect with the given BluetoothDevice
       /* try {
            // MY_UUID is the app's UUID string, also used by the server code
            //UUID MY_UUID = UUID.randomUUID();
            tmp = device.createRfcommSocketToServiceRecord(uuid);
        } catch (IOException e) { }
        mmSocket = tmp;
    }*/

    public void run() {
        // Cancel discovery because it will slow down the connection
        mBluetoothAdapter.cancelDiscovery();

        try {
            BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(mac);
            final UUID SERIAL_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
            mmSocket = device.createRfcommSocketToServiceRecord(SERIAL_UUID);
            mmSocket.connect();
            OutputStream out = mmSocket.getOutputStream();
            InputStream in = mmSocket.getInputStream();
            Log.e("TAG" , ""+out);
            // Connect the device through the socket. This will block
            // until it succeeds or throws an exception
           // mmSocket.connect();
        } catch (IOException connectException) {
            // Unable to connect; close the socket and get out
            try {
                mmSocket.close();
            } catch (IOException closeException) { }
            return;
        }

        // Do work to manage the connection (in a separate thread)
        //manageConnectedSocket(mmSocket);
        new ConnectedThread(mmSocket).start();
    }

    /** Will cancel an in-progress connection, and close the socket */
    public void cancel() {
        try {
            mmSocket.close();
        } catch (IOException e) { }
    }
}
}
  • 它与启动新Activity相同,并清除所有堆栈。
  • 或重新启动到MainActivity / FirstActivity。

答案 3 :(得分: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();
}

答案 4 :(得分: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"/>
    
  • 扩展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()的后退按钮。

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

答案 5 :(得分:11)

使用startActivity开始新活动后,请务必致电finish(),以便当前活动不会堆叠在新活动后面。

答案 6 :(得分:5)

高级可重复使用Kotlin:

您可以使用setter方法直接设置标志。在Kotlin中,or是Java的replacement按位或|

intent.flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK

如果您打算定期使用此功能,请创建一个Intent扩展功能

fun Intent.clearStack() {
    flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}

然后您可以在启动意图之前直接调用此函数

intent.clearStack()

如果需要在其他情况下添加其他标志的选项,请向扩展功能添加可选参数。

fun Intent.clearStack(additionalFlags: Int = 0) {
    flags = additionalFlags or Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}

答案 7 :(得分:4)

试试这个:

{{1}}

答案 8 :(得分:1)

Intent i = new Intent(MainPoliticalLogin.this, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);

答案 9 :(得分:1)

尝试以下代码,

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

答案 10 :(得分:0)

对我来说,上述方法没有 不起作用。

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

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

答案 11 :(得分:-1)

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

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

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

答案 12 :(得分:-1)

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