3. 导航栈核心组件与职责

3.1 四栈总体边界与分层

Android 导航体系中存在四个相互关联但又职责隔离的栈结构:Activity 栈、Fragment 栈、Task 栈和返回栈。它们分别管理不同粒度的界面单元与用户操作历史。下面表格定义每个栈的管理单元、生命周期锚点以及系统层归属。

栈名称管理单元生命周期锚点系统层级
Activity 栈(ActivityRecord 栈)ActivityRecord(单个 Activity 实例)onCreate → onStart → onResume → onPause → onStop → onDestroySystemServer / ActivityManagerService
Fragment 栈(BackStackRecord)Fragment 实例onAttach → onCreateView → onStart → onResume → onPause → onStop → onDestroyView → onDetachApp 进程 / FragmentManager
Task 栈(TaskRecord 栈)TaskRecord(一组 Activity 的集合)Task 被创建/移至前台/被覆盖/销毁(对应所有 Activity 生命周期)SystemServer / ActivityTaskManagerService
返回栈(ActivityStack 中的 mRecentTasks)TaskRecord 或 ActivityRecord(取决于启动模式)按最后操作时间排序,清除策略由系统决定SystemServer / SystemUI(最近任务)
边界总结:Activity 栈管理「可见 Activity」的实例堆叠;Fragment 栈管理「Fragment 事务」的逆向回退;Task 栈管理「任务容器」的层级与前台转移;返回栈管理「用户感知的历史 Tasks」。四者共同构成完整的导航栈体系,任何一层的状态不一致都会导致界面跳转异常或内存泄漏。

3.2 组件职责与信任链路

3.2.1 Activity 栈 —— 可见界面核心

Activity 栈由 ActivityManagerService 维护,以 ActivityRecord 为节点。每个 ActivityRecord 持有 ActivityInfo、TaskRecord 引用以及进程标识。其核心职责:

  • 维护前台 Activity 的焦点切换(resumedActivity)。
  • 处理启动模式(standard / singleTop / singleTask / singleInstance)对栈的操作。
  • 控制 Activity 生命周期转运(Pause → Stop → Destroy 等)。
  • 提供 ActivityStackSupervisor 对多 Display / 多栈协同管理。

3.2.2 Fragment 栈 —— 动态 UI 片断管理

Fragment 栈由 FragmentManager 内部的 BackStackRecord 链表实现。每个事务(FragmentTransaction)会生成一个 BackStackRecord,记录增删改操作。信任链路要求:

  • Fragment 栈的 pop 操作必须完全对应 push 时的逆操作,否则造成视图混乱。
  • Fragment 栈不能直接操作 Activity 栈,必须通过 FragmentManager 向宿主 Activity 发送回调。

3.2.3 Task 栈 —— 任务隔离与复用

TaskRecord 包含一个 ArrayList<ActivityRecord>,同时持有 mAffinity(任务亲和性)、mIntent、mRoot 等属性。Task 栈的信任边界:

  • 不同 Task 之间 Activity 不能直接互相访问(跨 Task 需通过 FLAG_ACTIVITY_NEW_TASK 等)。
  • 系统通过 isLockTaskMode 策略限制 Task 栈的修改。

3.2.4 返回栈 —— 用户心智模型映射

返回栈在 SystemUI 层以 RecentTasks 呈现,由 ActivityTaskManagerService 按最近使用时间排序。它并不直接管理 Activity 实例,而是管理 TaskSnapshot 快照。信任链路要求 SystemUI 通过 ITaskStackListener 监听栈变化。

常见风险点:若 Fragment 栈和 Activity 栈的回退操作不同步(例如用户按 Back 键时,Activity 栈 pop 而 Fragment 栈未清理),会导致 Fragment 泄漏或状态残留。解决方案是统一使用 Navigation Component 或自行封装导航控制器,将返回逻辑收敛至单一入口。

3.3 数据流与控制流

下图展示典型交互场景(按 BACK 键)中各栈间的控制流与数据流。

BACK 键事件在各栈间的控制流 INPUT(按键) SystemUI 返回键 ActivityManagerService Activity 栈 Fragment 栈 Task 栈 说明 实线箭头表示事件直接流向;虚线箭头表示状态回调通知。四栈间的信任链路必须保持单向。

3.4 选型权衡与落地步骤

3.4.1 是否需要独立管理 Fragment 栈?

  • 轻量屏内导航:可委托给系统 FragmentManager,无需自行包装。
  • 深度嵌套 + 复杂动画:建议在 Activity 栈基础上叠加自己的导航器,保留 BackStackRecord 的控制权。
  • 跨 Task 场景:不要依赖 Fragment 栈保持跨 Task 状态,应使用 onSaveInstanceState 持久化。

3.4.2 落地步骤(7 步)

  1. 定义自己的 RouteNode 数据结构,包含 intent/fragmentClass/栈类型标识。
  2. 创建 NavigationController 封装 startActivity 和 FragmentTransaction,禁止外部直接调用。
  3. 在 Activity.onBackPressed 中优先委托 NavigationController 处理。
  4. 注册 ActivityManagerInternal 的 Task 栈监听(SystemUI 需要)。
  5. 在 Task 切换或返回栈变化时,同步更新 UI 中的返回键状态及历史快照。
  6. 压力测试:频繁压榨 Back 键,验证 Activity/Fragment 栈无泄漏。
  7. 集成三方库时(如 Jetpack Navigation),确保其内部栈与自定义控制器不冲突。
验收标准(建议包含在课程练习中):
  • 在任意深度下连续按 Back 键,所有 Fragment 被正确回退,且 Activity 栈保持不变。
  • 从最近任务列表切换另一个 Task 后返回,原 Task 的 Activity 栈和 Fragment 栈恢复正确。
  • 通过 dumpsys activity activities 检查每个栈中 Record 数量符合预期。
  • SystemUI 状态栏返回键显示/隐藏逻辑与实际栈深度一致。