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 恢复的关键在于信任链不被破坏:
- 客户端生成:登录成功后下发签名 。
- 本地存储: 存入 EncryptedSharedPreferences,绑定设备指纹。
- 恢复验证:冷启动后从本地读取 ,发送至服务端校验。
- 续期机制:服务端返回 RefreshToken+AccessToken 双凭证。
- 销毁:用户主动登出或 过期后清除所有本地副本。
1.3.3 边界对照表
| 边界类型 | 定义 | 典型风险 |
|---|---|---|
| 时效边界 | Session 有效期(5min~7天) | 未过期但用户权限已变更 |
| 设备边界 | 单设备 vs 多设备登录 | 会话复制攻击 |
| 网络边界 | 内网/公网/离线模式 | 离线缓存与在线 Session 状态不一致 |
| 数据边界 | Session 可读取的数据域 | 越权访问其他用户的 Session 数据 |
1.4 数据流与控制流:状态保存与回话恢复路径
下图展示了从用户操作到状态保存、再从进程重建到会话恢复的完整数据流与控制流。重点标注了 Bundle 与 Session 的交互边界。
架构要点:恢复调度器是控制流的核心节点。它必须保持幂等性——多次调用同一恢复请求,不产生副作用。同时,恢复超时应设置 2s 的硬限,超时后直接进入降级路径。
1.5 选型权衡
| 选型维度 | 推荐方案 | 替代方案 | 权衡理由 |
|---|---|---|---|
| Bundle 序列化 | Parcelable + AutoValue | Serializable(反射慢、体积大) | 性能优先;Parcelable 减少 IPC 传输时间 40%+ |
| Session 存储 | EncryptedSharedPreferences | SQLite / Realm | 读写仅 1-3 个字段,SP 无锁开销;加密保护 |
| 恢复验证 | 双 模式(Access+Refresh) | 单长生命周期 | 减少续期频率,降低泄露风险窗口 |
| 离线 Session | 本地缓存 + 后台同步队列 | 完全离线禁用 | 用户体验优先,但需要冲突解决策略 |
1.6 风险点清单
- Bundle 数据溢出:超过 1MB 导致恢复崩溃。需引入
Bundle 审计切面,监控写入大小。 - 泄露:明文存储或日志打印。强制使用 EncryptedSharedPreferences 并清理日志输出。
- 恢复竞态:异步 Session 恢复尚未完成,但 UI 已渲染。使用状态机驱动恢复流程,UI 层等待恢复完成信号。
- 过期信任: 未过期但用户权限被撤销。增加服务端主动登出推送(WebSocket / Push)。
1.7 落地步骤
- 定义状态接口:明确哪些状态走 Bundle,哪些走 Session。输出《状态分类矩阵》。
- 实现 Bundle 审计:在
onSaveInstanceState前注入切面,统计 key/value 大小。 - 建立 Session 存储模块:封装 EncryptedSharedPreferences,提供
readSession() / writeSession() / clearSession()三个操作。 - 编写恢复调度器:状态机实现(IDLE→RESTORING→RESTORED→FAILED)。
- 集成信任校验:启动时从 Session 存储读取 ,调用服务端校验接口,处理续期逻辑。
1.8 验收标准
| 验收指标 | 最低阈值 | 理想阈值 | 验证方法 |
|---|---|---|---|
| Bundle 恢复成功率 | ≥ 99% | ≥ 99.9% | Monkey 测试 + 进程杀死后恢复 |
| Session 恢复成功率 | ≥ 98% | ≥ 99.5% | 冷启动后 校验通过率 |
| 恢复延迟(P99) | ≤ 3s | ≤ 1.5s | Trace + 日志打点 |
| Bundle 溢出率 | 0% | 0% | 自动化审计失败即阻断 |