是否可以在堆栈上启动活动,清除之前的整个历史记录?
情况
我有一个活动堆栈,可以是A-> B-> C或B-> C(屏幕A选择用户令牌,但许多用户只有一个令牌)。
在屏幕C中,用户可能采取使屏幕B无效的操作,因此应用程序希望将它们带到屏幕A,无论它是否已经在堆栈中。屏幕A应该是我的应用程序中堆栈中唯一的项目。
备注
还有许多其他类似的问题,但我没有找到任何可以解答这个确切问题的问题。我试着调用getParent().finish()
- 这总是会导致空指针异常。 FLAG_ACTIVITY_CLEAR_TOP
仅在活动已在堆栈中时才有效。
答案 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) { }
}
}
}
答案 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)
您可以使用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。