1、什么是 Activity 任务栈
Activity 任务栈(Task Stack)是 Android 系统中用于管理 Activity 的后进先出(LIFO)栈结构。每个任务栈包含一组相关的 Activity,用户可以通过返回键在这些 Activity 之间导航。
2、LIFO原则 /后进先出
后进先出原则:LIFO 全称:Last In, First Out,顾名思义就是后进来的任务栈先出去。
1、当启动一个新的 Activity(通过 startActivity),这个新的 Activity 会被创建并压入(Pushed)当前任务栈的栈顶,这叫入栈(Push)
2、当用户按下返回键,当前位于栈顶的 Activity 会被销毁(Finish),并从栈中弹出(Popped)。然后,下一个(即之前的一个)Activity 会恢复并显示给用户,这叫出栈(Pop)
3、任务栈的基本结构
任务栈示例:
┌─────────────────┐
│ Activity D │ ← 栈顶(当前显示)
├─────────────────┤
│ Activity C │
├─────────────────┤
│ Activity B │
├─────────────────┤
│ Activity A │ ← 栈底(根Activity)
└─────────────────┘
4、任务栈的创建
1. 应用启动时创建
当用户点击应用图标时,系统会自动创建主任务栈。
java
// AndroidManifest.xml 中配置主Activity
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
2. 通过 Intent Flag 创建新任务栈
java
// 创建新任务栈
Intent intent = new Intent(this, NewTaskActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
// 创建新任务栈并清除现有栈
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
3. 使用 taskAffinity 创建不同任务栈
xml
<!-- AndroidManifest.xml 中配置 -->
<activity
android:name=".DocumentActivity"
android:taskAffinity="com.example.app.document"
android:launchMode="standard">
</activity>
java
// 启动具有不同affinity的Activity
Intent intent = new Intent(this, DocumentActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
5、Launch Mode 对任务栈的影响
1. standard(标准模式)
java
// 默认模式,每次启动都创建新实例
Intent intent = new Intent(this, StandardActivity.class);
startActivity(intent);
- 总是创建新实例
- 放入当前任务栈栈顶
- 不影响任务栈结构
2. singleTop(栈顶复用)
java
// 如果已在栈顶则复用,否则创建新实例
Intent intent = new Intent(this, SingleTopActivity.class);
startActivity(intent);
- 栈顶已存在则调用onNewIntent()
- 不在栈顶则创建新实例
3. singleTask(栈内复用)
java
// 在指定affinity任务栈中寻找,清除其上所有Activity
Intent intent = new Intent(this, SingleTaskActivity.class);
startActivity(intent);
- 在指定affinity任务栈中寻找实例
- 如果存在则清除其上所有Activity并调到栈顶
- 如果不存在则创建新实例
4. singleInstance(单实例)
java
// 创建新的任务栈,且该栈中只能有这一个Activity
Intent intent = new Intent(this, SingleInstanceActivity.class);
startActivity(intent);
- 创建新的任务栈
- 该栈中只能包含这一个Activity
- 其他Activity不能进入这个栈
6、 任务栈的销毁
1. 正常返回销毁
java
// 按返回键销毁当前Activity
@Override
public void onBackPressed() {
super.onBackPressed(); // 销毁当前Activity,返回上一个
}
2. 程序化销毁单个Activity
java
// 销毁当前Activity
finish();
// 销毁后返回结果
setResult(RESULT_OK);
finish();
3. 清除整个任务栈
java
// 方法一:使用Intent Flag
Intent intent = new Intent(this, LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
// 方法二:使用finishAffinity()
finishAffinity(); // 销毁当前任务栈中所有同affinity的Activity
// 方法三:使用finishAndRemoveTask()
finishAndRemoveTask(); // 销毁Activity并移除任务栈
4. 清除部分任务栈
java
// 清除到指定Activity
Intent intent = new Intent(this, TargetActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
// 如果TargetActivity是singleTask,会清除其上的所有Activity
7、任务栈的管理和查询
1. 获取当前任务信息
java
// 获取ActivityManager
ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
// 获取当前任务ID
int taskId = getTaskId();
Log.d("TaskInfo", "当前任务ID: " + taskId);
// 获取任务栈中的Activity数量
int numActivities = getNumActivitiesInTask();
2. 检查任务栈中的Activity
java
public boolean isActivityInTask(Class<?> activityClass) {
ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
List<ActivityManager.AppTask> tasks = activityManager.getAppTasks();
for (ActivityManager.AppTask task : tasks) {
ActivityManager.RecentTaskInfo taskInfo = task.getTaskInfo();
if (taskInfo.baseActivity != null &&
taskInfo.baseActivity.getClassName().equals(activityClass.getName())) {
return true;
}
}
}
return false;
}
3. 任务栈状态监听
java
// 在Application中注册Activity生命周期回调
public class MyApp extends Application {
private List<Activity> activityStack = new ArrayList<>();
@Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
activityStack.add(activity);
Log.d("TaskStack", "Activity创建: " + activity.getClass().getSimpleName());
}
@Override
public void onActivityDestroyed(Activity activity) {
activityStack.remove(activity);
Log.d("TaskStack", "Activity销毁: " + activity.getClass().getSimpleName());
}
// 其他生命周期方法...
});
}
public List<Activity> getActivityStack() {
return new ArrayList<>(activityStack);
}
}
8、实际应用场景
1. 登录流程管理
java
// 登录成功后清除登录相关Activity
private void loginSuccess() {
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
finish();
}
2. 深度链接处理
java
// 处理深度链接,清理中间页面
private void handleDeepLink(Uri uri) {
Intent intent = new Intent(this, ProductDetailActivity.class);
intent.setData(uri);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
}
3. 退出应用
java
// 完全退出应用
public void exitApp() {
finishAffinity(); // 关闭所有同affinity的Activity
System.exit(0); // 完全退出进程
}
// 或者
public void exitApp() {
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finishAndRemoveTask();
}
9、注意事项
- 权限问题:查询其他任务栈可能需要特殊权限
- 版本兼容性:不同Android版本的任务栈行为可能不同
- 用户体验:合理使用任务栈管理,避免破坏用户导航预期
- 内存管理:及时销毁不需要的Activity,避免内存泄漏
10、 调试技巧
java
// 查看当前任务栈信息
private void dumpTaskStack() {
ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
List<ActivityManager.AppTask> tasks = activityManager.getAppTasks();
for (int i = 0; i < tasks.size(); i++) {
ActivityManager.RecentTaskInfo taskInfo = tasks.get(i).getTaskInfo();
Log.d("TaskDump", "Task " + i + ": " +
"base=" + (taskInfo.baseActivity != null ? taskInfo.baseActivity.getClassName() : "null") +
", top=" + (taskInfo.topActivity != null ? taskInfo.topActivity.getClassName() : "null"));
}
}
}