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"));
        }
    }
}
相关推荐
千里马学框架1 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台1 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone1 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc1 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo1 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077001 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼1 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone1 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen1 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone1 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui