1. Bundle与Session核心概念:状态与回话的关系

1.1 边界定义:状态与回话的职责分离

在移动端架构中,Bundle 与 Session 是两个职责完全不同的抽象层。Bundle 负责短时、瞬时、结构化的 UI 状态传输;Session 负责长时、跨界面、带安全上下文的用户会话管理。

维度 Bundle(状态容器) Session(回话上下文)
生命周期 与组件(Activity/Fragment)实例共存 跨多个组件,由登录/登出事件驱动
数据持久度 进程内恢复,进程杀死后丢失 持久化存储(/Redis/DB)
安全边界 无加密,纯内存传递 签名、加密、防篡改验证
序列化约束 仅支持 Parcelable / Serializable JSON / Protobuf / 自定义二进制
恢复场景 屏幕旋转、进程重建 网络断连、 过期重续
架构原则:坚持 Bundle 只存 UI 再现状态,Session 只存 用户身份与授权上下文。二者不应混用或互相代理。

1.2 Bundle 的构成与生命周期

Bundle 本质是一个 键-值 容器,但在架构上需要对其构成进行分层约束,以避免膨胀。

1.2.1 分层构成

  • UI 层状态:滚动位置、选中项、文本输入内容、弹窗可见性。
  • 业务层状态:当前请求 ID、分页游标、操作队列索引。
  • 数据层状态:实体 ID 列表、缓存校验和、未提交变更标记。

1.2.2 生命周期映射

onSaveInstanceState(outState)  → 写入 Bundle
onCreate(savedInstanceState)    → 读取 Bundle
onRestoreInstanceState(savedInstanceState) → 细粒度恢复

1.2.3 组件职责

组件 职责 反模式
Activity 保存根级导航状态、全局 UI 开关 将大对象(Bitmap/LargeList)写入 Bundle
Fragment 保存自身视图状态、子组件标识 在 Bundle 中存储 View 引用
ViewModel 不参与 Bundle,仅负责业务恢复 通过 Bundle 传递 LiveData/Flow
风险点:Bundle 默认有 1MB 大小限制。超出会触发 TransactionTooLargeException,导致应用崩溃或界面无法恢复。千万不可将 Session 或完整请求体放入 Bundle。

1.3 Session 的边界定义

Session 的边界不是物理的,而是逻辑的:它由 上下文范围、时效性、信任链 三个维度共同划定。

1.3.1 上下文边界

  • 应用级 Session:用户从登录到登出,跨所有 Activity/Fragment。
  • 业务级 Session:一次订单生命周期,跨多页面但限定在单个流程内。
  • 请求级 Session:单次 API 调用上下文,完成即销毁。

1.3.2 信任链路定义

Session 恢复的关键在于信任链不被破坏:

  1. 客户端生成:登录成功后下发签名 。
  2. 本地存储: 存入 EncryptedSharedPreferences,绑定设备指纹。
  3. 恢复验证:冷启动后从本地读取 ,发送至服务端校验。
  4. 续期机制:服务端返回 RefreshToken+AccessToken 双凭证。
  5. 销毁:用户主动登出或 过期后清除所有本地副本。

1.3.3 边界对照表

边界类型 定义 典型风险
时效边界 Session 有效期(5min~7天) 未过期但用户权限已变更
设备边界 单设备 vs 多设备登录 会话复制攻击
网络边界 内网/公网/离线模式 离线缓存与在线 Session 状态不一致
数据边界 Session 可读取的数据域 越权访问其他用户的 Session 数据

1.4 数据流与控制流:状态保存与回话恢复路径

下图展示了从用户操作到状态保存、再从进程重建到会话恢复的完整数据流与控制流。重点标注了 Bundle 与 Session 的交互边界。

数据流与控制流:Bundle状态保存与Session恢复宏观架构 用户操作(输入/导航) 组件状态收集 onSaveInstance Bundle 写入 Session 存储 会话状态 磁盘/DB (Bundle 文件) 安全存储 进程重建 / 冷启动 恢复调度器 (Dispatcher) onRestoreInstance 异步 Session 恢复验证 恢复确认/续期 信任校验边界 签名验证 | 设备指纹比对 验证请求 恢复成功 → UI 就绪 ⚠ 恢复失败:清除 Bundle/降级至匿名Session
架构要点:恢复调度器是控制流的核心节点。它必须保持幂等性——多次调用同一恢复请求,不产生副作用。同时,恢复超时应设置 2s 的硬限,超时后直接进入降级路径。

1.5 选型权衡

选型维度 推荐方案 替代方案 权衡理由
Bundle 序列化 Parcelable + AutoValue Serializable(反射慢、体积大) 性能优先;Parcelable 减少 IPC 传输时间 40%+
Session 存储 EncryptedSharedPreferences SQLite / Realm 读写仅 1-3 个字段,SP 无锁开销;加密保护
恢复验证 双 模式(Access+Refresh) 单长生命周期 减少续期频率,降低泄露风险窗口
离线 Session 本地缓存 + 后台同步队列 完全离线禁用 用户体验优先,但需要冲突解决策略

1.6 风险点清单

  1. Bundle 数据溢出:超过 1MB 导致恢复崩溃。需引入 Bundle 审计切面,监控写入大小。
  2. 泄露:明文存储或日志打印。强制使用 EncryptedSharedPreferences 并清理日志输出。
  3. 恢复竞态:异步 Session 恢复尚未完成,但 UI 已渲染。使用状态机驱动恢复流程,UI 层等待恢复完成信号。
  4. 过期信任: 未过期但用户权限被撤销。增加服务端主动登出推送(WebSocket / Push)。

1.7 落地步骤

  1. 定义状态接口:明确哪些状态走 Bundle,哪些走 Session。输出《状态分类矩阵》。
  2. 实现 Bundle 审计:在 onSaveInstanceState 前注入切面,统计 key/value 大小。
  3. 建立 Session 存储模块:封装 EncryptedSharedPreferences,提供 readSession() / writeSession() / clearSession() 三个操作。
  4. 编写恢复调度器:状态机实现(IDLE→RESTORING→RESTORED→FAILED)。
  5. 集成信任校验:启动时从 Session 存储读取 ,调用服务端校验接口,处理续期逻辑。

1.8 验收标准

验收指标 最低阈值 理想阈值 验证方法
Bundle 恢复成功率 ≥ 99% ≥ 99.9% Monkey 测试 + 进程杀死后恢复
Session 恢复成功率 ≥ 98% ≥ 99.5% 冷启动后 校验通过率
恢复延迟(P99) ≤ 3s ≤ 1.5s Trace + 日志打点
Bundle 溢出率 0% 0% 自动化审计失败即阻断