Android Activity 任务栈详解

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、注意事项

  1. 权限问题:查询其他任务栈可能需要特殊权限
  2. 版本兼容性:不同Android版本的任务栈行为可能不同
  3. 用户体验:合理使用任务栈管理,避免破坏用户导航预期
  4. 内存管理:及时销毁不需要的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"));
        }
    }
}
相关推荐
向阳花开_miemie29 分钟前
Android音频学习(二十)——高通HAL
android·学习·音视频
2501_925317131 小时前
博客SEO优化实战:从Google到百度,一套可复制的排名增长SOP
android·百度·rxjava
Charles豪1 小时前
MR、AR、VR:技术浪潮下安卓应用的未来走向
android·java·人工智能·xr·mr
2501_915921431 小时前
HTTPS 映射如何做?(HTTPS 映射配置、SNI 映射、TLS 终止、内网映射与 iOS 真机验证实战)
android·网络协议·ios·小程序·https·uni-app·iphone
TeleostNaCl1 小时前
SMBJ 简单使用指南 实现在 Java/Android 程序中访问 SMB 服务器
android·java·运维·服务器·经验分享·kotlin
小孔龙2 小时前
Kotlin 序列化:重复引用是技术问题还是架构缺陷?
android·kotlin·json
掘金一周2 小时前
2025年还有前端不会Nodejs ?| 掘金一周 9.25
android·前端·后端
2501_915106322 小时前
iOS 混淆与机器学习模型保护 在移动端保密权重与推理逻辑的实战指南(iOS 混淆、模型加密、ipa 加固)
android·人工智能·机器学习·ios·小程序·uni-app·iphone
低调小一2 小时前
从Android到iOS:启动监控实现的跨平台技术对比
android·ios·cocoa
雨白2 小时前
使用 Jetpack Compose 构建一个整洁架构笔记应用
android·android jetpack·mvvm