3-10.【Ability】分布式流转(Continuation)时生命周期如何变化?状态如何序列化?流转失败如何回滚?

2 阅读3分钟

分布式流转(Continuation)是 HarmonyOS 的杀手锏特性,它允许用户在一个设备上开始任务,然后在另一个设备上无缝继续。这不仅是跨端跳转,更是运行态栈(Runtime Stack)的迁移


1. 分布式流转中的生命周期变化

流转过程涉及两个设备(源端和对端)的协同,生命周期并不是简单的“A 关 B 开”,而是 “数据同步 -> 异地重建 -> 状态确认”

源端(Source Device)

  1. onContinue(wantParam): 流转的发起阶段。系统回调此接口,询问是否允许流转。
  2. 保持 Foreground: 在对端成功启动并加载 UI 之前,源端不会进入后台或销毁。这是为了防止流转失败导致任务彻底丢失。
  3. 流转完成/销毁: 一旦对端确认成功接管,源端根据业务需求可以选择 terminateSelf(销毁)或者留在后台。

对端(Target Device)

  1. onCreate(want, launchParam): 冷启动。此时 launchParam.launchReason 会被标记为 CONTINUATION
  2. onWindowStageCreate: 正常加载 UI。
  3. 数据恢复: 页面组件通过 aboutToAppearonPageShow 读取从源端传过来的序列化数据,恢复 UI 状态。

2. 状态如何序列化?

流转的本质是数据的跨端序列化。ArkTS 提供了 wantParam 作为数据的载体。

序列化规则:

  • 基础类型: string, number, boolean 等可以直接放入 wantParam.parameters
  • 复杂对象: 必须转换为 JSON 字符串ArrayBuffer
  • UI 状态: 开发者需要手动保存。例如:TextInput 的光标位置、List 的滚动偏移量、当前播放器的 Seek 时间点。

最佳实践:

不要试图通过流转传递“巨型”数据(如 100MB 的内存对象)。

  • 原则:ID 不传 实体
  • 机制: 源端将数据库 ID 传给对端,对端启动后利用分布式数据库(KV Store)或分布式文件系统同步拉取大数据量。

3. 流转失败如何回滚?

分布式环境复杂(Wi-Fi 断开、蓝牙干扰、对端内存不足),回滚机制(Rollback)是用户体验的最后一道防线。

失败检测机制

  • 系统超时: 如果对端在规定时间内没有成功执行 loadContent,系统会通知源端流转失败。
  • 逻辑拦截: 源端在 onContinue 中可以返回 REJECT(拒绝流转),例如当发现本地有未保存的敏感操作时。

如何处理回滚?

由于源端在流转期间一直处于 Foreground后台活跃 状态,回滚其实是一个**“状态保持”**的过程:

  1. 用户感知: 源端界面弹窗提示“流转失败,请重试”。
  2. 资源恢复: 如果源端为了流转已经暂时禁用了某些传感器(如陀螺仪),需要在失败回调中重新激活。
  3. 数据一致性: 确保流转产生的临时标记位(如 isContinuing)被重置,防止应用逻辑陷入死循环。

4. 关键代码模式

UIAbility 中,流转的逻辑通常如下:

TypeScript

// 源端保存
onContinue(wantParam: {[key: string]: any}): AbilityConstant.OnContinueResult {
  wantParam['progress'] = this.currentProgress; // 保存进度
  return AbilityConstant.OnContinueResult.AGREE;
}

// 对端恢复
onCreate(want, launchParam) {
  if (launchParam.launchReason === AbilityConstant.LaunchReason.CONTINUATION) {
    this.restoredProgress = want.parameters['progress']; // 恢复进度
  }
}

总结

特性普通跳转 (startAbility)分布式流转 (Continuation)
核心目的切换功能模块切换硬件设备
状态载体基础 Want 参数深度序列化 wantParam + 分布式数据
源端命运通常进入 Background保持存活直至对端确认
失败后果页面无法跳转触发回滚,源端恢复交互

一句话建议: 把流转看作是一次“带行李的跨国旅行”。行李(数据)要打包得精简,护照(wantParam)要对齐,如果签证(连接)失败,赶紧回自己家(回滚)坐好。