7.2 跨设备协同与多设备流转


7.2 跨设备协同与多设备流转

本节摘要:流转(continuation)让 UIAbility 的界面与状态跨设备迁移。本节配置流转能力、实现"从手机迁到平板"的完整链路,讲清随行状态的组织方式与分布式数据对象的最小用法,并给出失败兜底的设计。

把页面搬到平板上

场景直白:用户在手机上写备忘写到一半,想换平板的大屏继续。期望的体验是点一下"流转",平板亮起,内容原样出现,手机侧收尾。拆开看这条链路要做四件事:配置声明应用支持迁移、发起方选择目标设备并请求迁移、对端被拉起并恢复状态、发起方善后。

第一步是配置。在模块的 module.json5 里给 EntryAbility 开启迁移能力:

{ "module": { "abilities": [ { "name": "EntryAbility", "srcEntry": "./ets/entryability/EntryAbility.ets", "continuable": true } ] } }

continuable 一行就是应用的迁移开关。第二步,界面上的"流转"按钮调用迁移接口:

import { continuationManager } from '@kit.DistributedServiceKit'; import { BusinessError } from '@kit.BasicServicesKit'; async function startContinuation(): Promise<void> { try { const token = await continuationManager.startContinuationDeviceManager( undefined, continuationManager.ContinuationMode.PICK ); hilog.info(0x0001, 'Continuation', '选择器令牌已获取'); } catch (e) { const err = e as BusinessError; hilog.error(0x0001, 'Continuation', `发起失败 ${err.code}`); } }

PICK 模式会拉起系统的设备选择器(也可以自绘设备列表后用指定模式直连)。用户在弹出的面板里选中平板,系统接管后续:对端拉起同应用、发起方收到回调。第三、四步都发生在 UIAbility 的生命周期回调里——这正是第 2 章埋的伏笔兑现的地方:迁移前后,onContinue 准备随行数据:

import { AbilityConstant } from '@kit.AbilityKit'; import Want from '@ohos.app.ability.Want'; export default class EntryAbility extends UIAbility { onContinue(wantParam: Record<string, Object>): AbilityConstant.OnContinueResult { wantParam['draft'] = this.currentDraft; wantParam['scrollOffset'] = this.scrollOffset; return AbilityConstant.OnContinueResult.AGREE; } }

onContinue 在迁移发起时被调用:把要带走的轻量数据塞进 wantParam,返回 AGREE 表示同意迁移。对端拉起时走 onCreate,从 want 里取回:

onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { if (launchParam.launchReason === AbilityConstant.LaunchReason.CONTINUATION) { this.currentDraft = (want.parameters?.['draft'] as string) ?? ''; this.scrollOffset = (want.parameters?.['scrollOffset'] as number) ?? 0; } }

LaunchReason 为 CONTINUATION 标明这是一次迁移启动而非冷启动,随行数据从 want.parameters 取回,页面加载后恢复滚动位置与草稿内容。

图:一次迁移的时序与状态去向

图:一次迁移的时序与状态去向

分布式数据对象:迁移之外的持续同步

onContinue 适合"搬一次",两台设备要持续看同一份数据(比如双端协作编辑),用分布式数据对象。它是把一个 JS 对象挂到分布式会话上,任何一端改,另一端自动收到:

import { distributedDataObject } from '@kit.ArkData'; let session: distributedDataObject.DataObject | undefined; async function joinCollab(context: Context, docId: string): Promise<void> { const target: Record<string, Object> = { 'docId': docId, 'text': '' }; session = distributedDataObject.create(context, target); session.setSessionId(`collab-${docId}`); session.on('change', () => { const text = (session!.getObject()['text'] as string); this.applyRemoteText(text); }); } function editText(next: string): void { session?.put('text', next); }

setSessionId 让两端加入同一会话(会话标识用业务 ID 拼),put 修改字段,change 事件在对端触发。它的心智模型与第 4 章的状态装饰器神似——也是"改数据、界面自动跟",只是作用域从组件树扩大到了设备群。数据量与复杂查询不适用(那是分布式 KV 表的领域,思路相同接口更全),协作场景的小对象正合适。

兜底与体验细节

迁移不是总能成功:对端离线、版本不匹配、用户取消。设计上有三条纪律。其一,onContinue 里不要做耗时操作,准备数据要快,超时会被系统放弃迁移。其二,失败路径给用户明确反馈并保持本端状态无损——迁移失败时用户应该"什么都没发生"般继续编辑,而不是丢了一半状态。其三,两端版本兼容:wantParam 的数据格式随版本演进时,接收端要能容错旧格式,缺字段走默认值(第 6.1 节解析纪律的同款思路)。

演练收尾:在双模拟器上完整走一遍——手机写半句备忘、点流转、选平板、平板出现同内容且光标位置合理;再测失败路径(迁移前关掉平板实例),确认手机侧提示明确、编辑状态无损。两个实验都过关,你才算真正"会用"流转而不只是"会调"接口。

⚠️ 常见坑:把大数据(整份文档、图片转义串)塞进 onContinue 的 wantParam。随行数据有大小约束,超限迁移静默失败。大对象走分布式数据对象或先落库再迁移后拉取,wantParam 只放"最小现场"。

💡 关键直觉:迁移的本质是"重建上下文"而不是"搬运进程"。想清楚用户继续工作需要哪些最小上下文(草稿、位置、选中项),迁移设计就完成了大半——这也是评估任何"接续体验"产品的通用标尺。

本节要点回顾:

  • 四步链路:continuable 配置、PICK 选择器发起、对端 CONTINUATION 启动恢复、发起方收尾。
  • onContinue 纪律:最小现场、不耗时、返回 AGREE;大数据不入 wantParam。
  • 分布式数据对象:会话标识绑定两端,put 与 change 构成持续同步,适合协作小对象。
  • 失败兜底:本端无损、反馈明确、格式前向兼容。
  • 设计标尺:迁移 = 重建用户继续工作所需的最小上下文。

界面可以跨设备了,服务还能更轻一步——不安装应用就触达用户。下一节的元服务与卡片,是 HarmonyOS 服务生态的另一种交付形态。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U