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"));
        }
    }
}
相关推荐
idward3073 小时前
Android的USB通信 (AOA Android开放配件协议)
android·linux
且随疾风前行.3 小时前
Android Binder 驱动 - Media 服务启动流程
android·microsoft·binder
恋猫de小郭3 小时前
Flutter 真 3D 游戏引擎来了,flame_3d 了解一下
android·前端·flutter
一笑的小酒馆3 小时前
Android使用Flow+协程封装一个FlowBus
android
一笑的小酒馆4 小时前
Android15适配16kb
android
CYRUS_STUDIO5 小时前
FART 脱壳不再全量!用一份配置文件精准控制节奏与范围
android·c++·逆向
mooyuan天天5 小时前
DVWA靶场通关笔记-SQL Injection Blind(SQL盲注 Impossible级别)
android·笔记·sql
CYRUS_STUDIO5 小时前
FART 自动化脱壳框架优化实战:Bug 修复与代码改进记录
android·操作系统·逆向
王喵喵喵5 小时前
每天一个安卓测试开发小知识之 (四)---常用的adb shell命令第二期 pm命令
android·测试