HarmonyOS APP开发之Continuation开发
小知识
前面两篇文章聊的都是Ability迁移,但HarmonyOS的分布式能力不止于此。Continuation(继续能力)是一个更灵活、更轻量的跨设备流转机制。
打个比方,Ability迁移像是"搬家"——整个应用打包带走;而Continuation像是"串门"——你可以只带走某个功能模块,或者在不同设备上同时运行同一个应用的不同部分。
举个例子:你在手机上看地图导航,想用平板看更大的地图,但手机上还想继续听语音导航。这种场景下,Ability迁移就不合适了——它会完全把应用"搬走",手机上就没法继续用了。这时候就需要Continuation,它可以让地图界面流转到平板,而语音播报继续在手机上运行。
Continuation的核心思想是"按需流转"——不是全有或全无,而是根据场景选择需要流转的部分。这种灵活性,让分布式体验更加自然。
核心原理
Continuation架构
Continuation基于以下几个核心概念:
- ContinuationRegisterManager:注册管理器,负责声明可流转的能力
- ContinuationDeviceManager:设备管理器,负责设备发现和选择
- ContinuationContext:流转上下文,负责实际的流转操作
- ContinuationState:流转状态,追踪流转的进度和结果
Continuation与Ability迁移的区别
| 特性 | Ability迁移 | Continuation |
|---|---|---|
| 流转粒度 | 整个Ability | 可指定的Ability或组件 |
| 源设备状态 | 冻结或销毁 | 可继续运行 |
| 回迁支持 | 需要显式触发 | 自动支持 |
| 适用场景 | 完全切换设备 | 多设备协同 |
| 灵活性 | 较低 | 较高 |
Continuation生命周期
// Continuation状态流转
enum ContinuationStage {
IDLE = 'idle', // 空闲,未发起流转
CONNECTING = 'connecting', // 正在连接目标设备
TRANSFERRING = 'transferring', // 正在传输数据
ACTIVE = 'active', // 流转激活,目标设备运行中
REVERSING = 'reversing', // 正在回迁
DISCONNECTED = 'disconnected' // 已断开
}
代码实战
示例一:基础Continuation注册与流转
这是最基础的Continuation使用示例,展示如何注册流转能力并发起流转。
// ContinuationManager.ets
import continuationManager from '@ohos.continuationManager';
import deviceManager from '@ohos.distributedDeviceManager';
import Want from '@ohos.app.ability.Want';
import common from '@ohos.app.ability.common';
export class ContinuationManager {
private context: common.UIAbilityContext;
private continuationManager: continuationManager.ContinuationManager | null = null;
private deviceManager: deviceManager.DeviceManager | null = null;
private continuationToken: string = '';
// 流转状态回调
private onStateChange: ((state: ContinuationStage) => void) | null = null;
private onDeviceChange: ((devices: DeviceInfo[]) => void) | null = null;
constructor(context: common.UIAbilityContext) {
this.context = context;
}
// 初始化Continuation管理器
async initialize(): Promise<void> {
console.info('[ContinuationManager] Initializing...');
try {
// 1. 创建设备管理器
this.deviceManager = deviceManager.createDeviceManager(
this.context.applicationInfo.name
);
// 2. 创建Continuation管理器
this.continuationManager = continuationManager.createContinuationManager(
this.context.applicationInfo.name
);
// 3. 注册Continuation能力
await this.registerContinuation();
// 4. 监听设备变化
this.setupDeviceListener();
console.info('[ContinuationManager] Initialized successfully');
} catch (error) {
console.error('[ContinuationManager] Initialize failed:', error);
throw error;
}
}
// 注册Continuation能力
private async registerContinuation(): Promise<void> {
if (!this.continuationManager) return;
// 定义可流转的Ability信息
const continuationInfo: continuationManager.ContinuationInfo = {
deviceType: continuationManager.DeviceType.DEVICE_TYPE_PHONE |
continuationManager.DeviceType.DEVICE_TYPE_TABLET |
continuationManager.DeviceType.DEVICE_TYPE_TV,
// 过滤条件:只流转特定Ability
filter: {
bundleName: this.context.applicationInfo.name,
abilityName: 'MainAbility'
}
};
// 注册并获取token
this.continuationToken = await this.continuationManager.register(continuationInfo);
console.info('[ContinuationManager] Registered, token:', this.continuationToken);
// 监听流转状态变化
this.continuationManager.on('continuationStateChange',
(token: string, deviceId: string, state: continuationManager.ContinuationState) => {
this.handleStateChange(token, deviceId, state);
});
}
// 设置设备监听
private setupDeviceListener(): void {
if (!this.deviceManager) return;
// 监听设备上线
this.deviceManager.on('deviceStateChange', (data: deviceManager.DeviceInfo) => {
console.info('[ContinuationManager] Device state changed:',
data.deviceName, data.deviceState);
// 刷新设备列表
this.refreshDeviceList();
});
// 初始获取设备列表
this.refreshDeviceList();
}
// 刷新设备列表
private async refreshDeviceList(): Promise<void> {
if (!this.deviceManager) return;
try {
const devices = this.deviceManager.getTrustedDeviceListSync();
// 转换为统一的设备信息格式
const deviceInfos: DeviceInfo[] = devices.map(d => ({
deviceId: d.deviceId,
deviceName: d.deviceName,
deviceType: this.mapDeviceType(d.deviceType),
isOnline: d.deviceState === deviceManager.DeviceState.ONLINE
}));
// 通知设备列表更新
if (this.onDeviceChange) {
this.onDeviceChange(deviceInfos);
}
} catch (error) {
console.error('[ContinuationManager] Failed to refresh devices:', error);
}
}
// 发起流转
async startContinuation(targetDeviceId: string): Promise<boolean> {
console.info('[ContinuationManager] Starting continuation to:', targetDeviceId);
if (!this.continuationManager || !this.continuationToken) {
console.error('[ContinuationManager] Not initialized');
return false;
}
try {
// 通知状态变化
this.notifyStateChange(ContinuationStage.CONNECTING);
// 构建流转参数
const connectOptions: continuationManager.ConnectOptions = {
deviceId: targetDeviceId,
// 流转模式:PUSH推送到目标设备
continuationMode: continuationManager.ContinuationMode.PUSH,
// 回迁模式:支持自动回迁
reversible: true
};
// 发起流转
await this.continuationManager.connect(this.continuationToken, connectOptions);
console.info('[ContinuationManager] Continuation started');
this.notifyStateChange(ContinuationStage.TRANSFERRING);
return true;
} catch (error) {
console.error('[ContinuationManager] Start continuation failed:', error);
this.notifyStateChange(ContinuationStage.IDLE);
return false;
}
}
// 取消流转
async cancelContinuation(): Promise<void> {
if (!this.continuationManager || !this.continuationToken) return;
try {
await this.continuationManager.disconnect(this.continuationToken);
console.info('[ContinuationManager] Continuation cancelled');
this.notifyStateChange(ContinuationStage.IDLE);
} catch (error) {
console.error('[ContinuationManager] Cancel failed:', error);
}
}
// 处理流转状态变化
private handleStateChange(
token: string,
deviceId: string,
state: continuationManager.ContinuationState
): void {
console.info('[ContinuationManager] State changed:', state);
switch (state) {
case continuationManager.ContinuationState.CONNECTED:
this.notifyStateChange(ContinuationStage.ACTIVE);
break;
case continuationManager.ContinuationState.DISCONNECTED:
this.notifyStateChange(ContinuationStage.DISCONNECTED);
break;
case continuationManager.ContinuationState.REVERSING:
this.notifyStateChange(ContinuationStage.REVERSING);
break;
}
}
// 通知状态变化
private notifyStateChange(state: ContinuationStage): void {
if (this.onStateChange) {
this.onStateChange(state);
}
}
// 设备类型映射
private mapDeviceType(type: number): DeviceType {
switch (type) {
case 1: return DeviceType.PHONE;
case 2: return DeviceType.TABLET;
case 3: return DeviceType.TV;
case 4: return DeviceType.WATCH;
default: return DeviceType.UNKNOWN;
}
}
// 设置回调
setOnStateChange(callback: (state: ContinuationStage) => void): void {
this.onStateChange = callback;
}
setOnDeviceChange(callback: (devices: DeviceInfo[]) => void): void {
this.onDeviceChange = callback;
}
// 销毁
destroy(): void {
if (this.continuationManager && this.continuationToken) {
this.continuationManager.unregister(this.continuationToken);
continuationManager.releaseContinuationManager(this.continuationManager);
}
if (this.deviceManager) {
deviceManager.releaseDeviceManager(this.deviceManager);
}
this.continuationManager = null;
this.deviceManager = null;
}
}
// 枚举定义
enum ContinuationStage {
IDLE = 'idle',
CONNECTING = 'connecting',
TRANSFERRING = 'transferring',
ACTIVE = 'active',
REVERSING = 'reversing',
DISCONNECTED = 'disconnected'
}
enum DeviceType {
UNKNOWN = 'unknown',
PHONE = 'phone',
TABLET = 'tablet',
TV = 'tv',
WATCH = 'watch'
}
interface DeviceInfo {
deviceId: string;
deviceName: string;
deviceType: DeviceType;
isOnline: boolean;
}
示例二:带状态同步的Continuation
Continuation流转时需要同步应用状态,这个示例展示如何在流转过程中传递和恢复状态。
// StatefulContinuationAbility.ets
import UIAbility from '@ohos.app.ability.UIAbility';
import Want from '@ohos.app.ability.Want';
import AbilityConstant from '@ohos.app.ability.AbilityConstant';
import continuationManager from '@ohos.continuationManager';
export default class StatefulContinuationAbility extends UIAbility {
// 应用状态
private appState: ApplicationState = {
currentPage: 'home',
userPreferences: {},
navigationStack: [],
formData: {}
};
// Continuation管理器
private continuationManager: continuationManager.ContinuationManager | null = null;
private continuationToken: string = '';
async onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): Promise<void> {
console.info('[StatefulAbility] onCreate');
// 初始化Continuation
await this.initContinuation();
// 处理Continuation启动
if (launchParam.launchReason === AbilityConstant.LaunchReason.CONTINUATION) {
this.restoreStateFromContinuation(want);
}
}
// 初始化Continuation
private async initContinuation(): Promise<void> {
try {
this.continuationManager = continuationManager.createContinuationManager(
this.context.applicationInfo.name
);
// 注册时指定状态保存回调
const info: continuationManager.ContinuationInfo = {
deviceType: continuationManager.DeviceType.DEVICE_TYPE_PHONE |
continuationManager.DeviceType.DEVICE_TYPE_TABLET,
// 关键:指定状态保存回调
onSaveState: (want: Want): boolean => {
return this.onSaveContinuationState(want);
},
// 指定状态恢复回调
onRestoreState: (want: Want): boolean => {
return this.onRestoreContinuationState(want);
}
};
this.continuationToken = await this.continuationManager.register(info);
console.info('[StatefulAbility] Continuation registered');
} catch (error) {
console.error('[StatefulAbility] Init failed:', error);
}
}
// 保存Continuation状态
private onSaveContinuationState(want: Want): boolean {
console.info('[StatefulAbility] Saving continuation state');
// 序列化当前状态
const stateData: ContinuationStateData = {
// 页面信息
currentPage: this.appState.currentPage,
// 导航栈
navigationStack: JSON.stringify(this.appState.navigationStack),
// 用户偏好
userPreferences: JSON.stringify(this.appState.userPreferences),
// 表单数据(如果有未提交的表单)
formData: JSON.stringify(this.appState.formData),
// 时间戳
timestamp: Date.now(),
// 版本号(用于兼容性检查)
version: '1.0'
};
// 写入Want参数
want.parameters = {
...want.parameters,
'continuationState': JSON.stringify(stateData)
};
return true;
}
// 恢复Continuation状态
private onRestoreContinuationState(want: Want): boolean {
console.info('[StatefulAbility] Restoring continuation state');
if (!want.parameters?.['continuationState']) {
console.warn('[StatefulAbility] No continuation state found');
return false;
}
try {
const stateData: ContinuationStateData =
JSON.parse(want.parameters['continuationState'] as string);
// 版本兼容性检查
if (stateData.version !== '1.0') {
console.warn('[StatefulAbility] Version mismatch:', stateData.version);
return false;
}
// 恢复状态
this.appState.currentPage = stateData.currentPage;
this.appState.navigationStack = JSON.parse(stateData.navigationStack);
this.appState.userPreferences = JSON.parse(stateData.userPreferences);
this.appState.formData = JSON.parse(stateData.formData);
// 计算流转耗时
const elapsed = Date.now() - stateData.timestamp;
console.info('[StatefulAbility] State restored, elapsed:', elapsed, 'ms');
return true;
} catch (error) {
console.error('[StatefulAbility] Restore failed:', error);
return false;
}
}
// 发起Continuation
async continueTo(targetDeviceId: string): Promise<void> {
if (!this.continuationManager || !this.continuationToken) {
console.error('[StatefulAbility] Continuation not initialized');
return;
}
try {
// 在发起流转前,保存最新状态
this.saveCurrentState();
// 发起流转
await this.continuationManager.connect(this.continuationToken, {
deviceId: targetDeviceId,
continuationMode: continuationManager.ContinuationMode.PUSH,
reversible: true
});
console.info('[StatefulAbility] Continuation started');
} catch (error) {
console.error('[StatefulAbility] Continue failed:', error);
}
}
// 保存当前状态(在流转前调用)
private saveCurrentState(): void {
// 从UI获取最新状态
const currentPage = AppStorage.get<string>('currentPage') || 'home';
const navStack = AppStorage.get<any[]>('navigationStack') || [];
const formData = AppStorage.get<Record<string, any>>('formData') || {};
this.appState.currentPage = currentPage;
this.appState.navigationStack = navStack;
this.appState.formData = formData;
console.info('[StatefulAbility] Current state saved');
}
// 从Continuation恢复状态
private restoreStateFromContinuation(want: Want): void {
if (this.onRestoreContinuationState(want)) {
// 通知UI恢复
this.notifyUIRestore();
}
}
// 通知UI恢复状态
private notifyUIRestore(): void {
// 通过AppStorage通知页面
AppStorage.setOrCreate('restorePage', this.appState.currentPage);
AppStorage.setOrCreate('restoreNavStack', this.appState.navigationStack);
AppStorage.setOrCreate('restoreFormData', this.appState.formData);
AppStorage.setOrCreate('restoreUserPrefs', this.appState.userPreferences);
console.info('[StatefulAbility] UI notified for restore');
}
// 更新应用状态(供UI调用)
updateAppState(key: string, value: any): void {
switch (key) {
case 'currentPage':
this.appState.currentPage = value;
break;
case 'formData':
this.appState.formData = value;
break;
default:
this.appState.userPreferences[key] = value;
}
}
}
// 接口定义
interface ApplicationState {
currentPage: string;
userPreferences: Record<string, any>;
navigationStack: any[];
formData: Record<string, any>;
}
interface ContinuationStateData {
currentPage: string;
navigationStack: string;
userPreferences: string;
formData: string;
timestamp: number;
version: string;
}
示例三:多设备协同Continuation
Continuation的强大之处在于支持多设备协同——同一应用可以同时在多个设备上运行,各司其职。
// MultiDeviceContinuation.ets
import continuationManager from '@ohos.continuationManager';
import deviceManager from '@ohos.distributedDeviceManager';
import distributedData from '@ohos.data.distributedData';
export class MultiDeviceContinuation {
private continuationManager: continuationManager.ContinuationManager | null = null;
private deviceManager: deviceManager.DeviceManager | null = null;
private kvStore: distributedData.SingleKVStore | null = null;
// 活跃的Continuation会话
private activeSessions: Map<string, ContinuationSession> = new Map();
async initialize(): Promise<void> {
// 初始化管理器
this.continuationManager = continuationManager.createContinuationManager('com.example.app');
this.deviceManager = deviceManager.createDeviceManager('com.example.app');
// 初始化分布式数据存储,用于多设备间状态同步
await this.initDistributedStore();
// 注册Continuation
await this.registerMultiDeviceContinuation();
}
// 初始化分布式存储
private async initDistributedStore(): Promise<void> {
const kvManager = distributedData.createKVManager({
bundleName: 'com.example.app',
userInfo: { userId: 'default', userType: distributedData.UserType.SAME_USER_ID }
});
this.kvStore = await kvManager.getKVStore({
storeId: 'multi_device_continuation',
securityLevel: distributedData.SecurityLevel.S1
});
// 监听远程数据变化
this.kvStore.on('dataChange', distributedData.SubscribeType.SUBSCRIBE_TYPE_REMOTE,
(data: distributedData.ChangeNotification) => {
this.handleRemoteSync(data);
});
}
// 注册多设备Continuation
private async registerMultiDeviceContinuation(): Promise<void> {
if (!this.continuationManager) return;
const info: continuationManager.ContinuationInfo = {
deviceType: continuationManager.DeviceType.DEVICE_TYPE_PHONE |
continuationManager.DeviceType.DEVICE_TYPE_TABLET |
continuationManager.DeviceType.DEVICE_TYPE_TV,
// 关键:使用COLLABORATE模式,允许多设备同时运行
continuationMode: continuationManager.ContinuationMode.COLLABORATE
};
const token = await this.continuationManager.register(info);
// 监听新设备连接
this.continuationManager.on('deviceConnect',
(deviceId: string, session: continuationManager.ContinuationSession) => {
this.handleDeviceConnect(deviceId, session);
});
// 监听设备断开
this.continuationManager.on('deviceDisconnect',
(deviceId: string) => {
this.handleDeviceDisconnect(deviceId);
});
}
// 处理设备连接
private handleDeviceConnect(
deviceId: string,
session: continuationManager.ContinuationSession
): void {
console.info('[MultiDevice] Device connected:', deviceId);
// 创建会话记录
const continuationSession: ContinuationSession = {
deviceId: deviceId,
sessionId: session.sessionId,
role: this.determineDeviceRole(deviceId),
connectedAt: Date.now(),
state: 'active'
};
this.activeSessions.set(deviceId, continuationSession);
// 根据设备角色分配任务
this.assignTaskByRole(continuationSession);
// 同步当前状态到新设备
this.syncStateToDevice(deviceId);
}
// 处理设备断开
private handleDeviceDisconnect(deviceId: string): void {
console.info('[MultiDevice] Device disconnected:', deviceId);
const session = this.activeSessions.get(deviceId);
if (session) {
// 重新分配该设备的任务
this.reassignTasks(session);
// 移除会话记录
this.activeSessions.delete(deviceId);
}
}
// 确定设备角色
private determineDeviceRole(deviceId: string): DeviceRole {
if (!this.deviceManager) return DeviceRole.UNKNOWN;
const devices = this.deviceManager.getTrustedDeviceListSync();
const device = devices.find(d => d.deviceId === deviceId);
if (!device) return DeviceRole.UNKNOWN;
// 根据设备类型分配角色
switch (device.deviceType) {
case 3: // TV
return DeviceRole.DISPLAY; // 显示角色:展示内容
case 2: // Tablet
return DeviceRole.CONTROL; // 控制角色:交互操作
case 1: // Phone
return DeviceRole.INPUT; // 输入角色:数据输入
default:
return DeviceRole.AUXILIARY;
}
}
// 根据角色分配任务
private assignTaskByRole(session: ContinuationSession): void {
console.info('[MultiDevice] Assigning task for role:', session.role);
const taskAssignment: TaskAssignment = {
deviceId: session.deviceId,
role: session.role,
tasks: []
};
switch (session.role) {
case DeviceRole.DISPLAY:
// 显示设备:负责渲染主内容
taskAssignment.tasks = ['render_main_content', 'display_fullscreen'];
break;
case DeviceRole.CONTROL:
// 控制设备:负责交互控制
taskAssignment.tasks = ['handle_interaction', 'show_controls'];
break;
case DeviceRole.INPUT:
// 输入设备:负责数据输入
taskAssignment.tasks = ['handle_input', 'show_input_panel'];
break;
}
// 保存任务分配到分布式存储
this.saveTaskAssignment(taskAssignment);
// 通知设备执行任务
this.notifyDeviceTask(session.deviceId, taskAssignment);
}
// 重新分配任务
private reassignTasks(disconnectedSession: ContinuationSession): void {
console.info('[MultiDevice] Reassigning tasks from:', disconnectedSession.deviceId);
// 获取其他活跃设备
const activeDevices = Array.from(this.activeSessions.values());
if (activeDevices.length === 0) {
// 没有其他设备,本地承担所有任务
this.takeOverAllTasks();
return;
}
// 根据剩余设备的角色重新分配
const tasksToReassign = this.getTasksByRole(disconnectedSession.role);
for (const task of tasksToReassign) {
// 找到最适合承担该任务的设备
const targetDevice = this.findBestDeviceForTask(task, activeDevices);
if (targetDevice) {
this.assignTaskToDevice(task, targetDevice);
}
}
}
// 同步状态到设备
private async syncStateToDevice(deviceId: string): Promise<void> {
if (!this.kvStore) return;
// 获取当前完整状态
const currentState = await this.getCurrentState();
// 发送到目标设备
await this.kvStore.put(`sync_${deviceId}`, {
key: `sync_${deviceId}`,
value: JSON.stringify(currentState)
});
}
// 处理远程同步
private handleRemoteSync(data: distributedData.ChangeNotification): void {
if (!data.updateRecords || data.updateRecords.length === 0) return;
for (const record of data.updateRecords) {
const key = record.key;
if (key.startsWith('task_')) {
// 任务分配更新
this.applyTaskAssignment(JSON.parse(record.value.value as string));
} else if (key.startsWith('sync_')) {
// 状态同步
this.applyStateSync(JSON.parse(record.value.value as string));
}
}
}
// 保存任务分配
private async saveTaskAssignment(assignment: TaskAssignment): Promise<void> {
if (!this.kvStore) return;
await this.kvStore.put(`task_${assignment.deviceId}`, {
key: `task_${assignment.deviceId}`,
value: JSON.stringify(assignment)
});
}
// 通知设备任务
private notifyDeviceTask(deviceId: string, assignment: TaskAssignment): void {
// 通过Continuation发送消息
if (this.continuationManager) {
this.continuationManager.sendData(deviceId, {
type: 'task_assignment',
assignment: assignment
});
}
}
// 辅助方法
private async getCurrentState(): Promise<any> {
return {}; // 实际实现需要获取当前状态
}
private applyTaskAssignment(assignment: TaskAssignment): void {
console.info('[MultiDevice] Applying task assignment:', assignment);
}
private applyStateSync(state: any): void {
console.info('[MultiDevice] Applying state sync');
}
private getTasksByRole(role: DeviceRole): string[] {
return []; // 实际实现
}
private findBestDeviceForTask(task: string, devices: ContinuationSession[]): ContinuationSession | null {
return devices[0] || null; // 实际实现
}
private assignTaskToDevice(task: string, device: ContinuationSession): void {
console.info('[MultiDevice] Assigning task to device:', task, device.deviceId);
}
private takeOverAllTasks(): void {
console.info('[MultiDevice] Taking over all tasks');
}
}
// 枚举和接口
enum DeviceRole {
UNKNOWN = 'unknown',
DISPLAY = 'display',
CONTROL = 'control',
INPUT = 'input',
AUXILIARY = 'auxiliary'
}
interface ContinuationSession {
deviceId: string;
sessionId: string;
role: DeviceRole;
connectedAt: number;
state: 'active' | 'inactive' | 'disconnecting';
}
interface TaskAssignment {
deviceId: string;
role: DeviceRole;
tasks: string[];
}
踩坑与注意事项
坑一:Continuation注册时机错误
问题描述:在Ability的onCreate中注册Continuation,但此时UI还未创建,导致状态保存回调无法获取UI数据。
解决方案:在onWindowStageCreate后注册,或在状态保存时从AppStorage获取数据。
坑二:设备角色分配冲突
问题描述:多设备协同时,两个相同类型的设备连接,角色分配产生冲突。
解决方案:实现优先级机制
private determineDeviceRoleWithPriority(deviceId: string, existingRoles: DeviceRole[]): DeviceRole {
const baseRole = this.determineDeviceRole(deviceId);
// 如果该角色已被占用,降级为辅助角色
if (existingRoles.includes(baseRole)) {
return DeviceRole.AUXILIARY;
}
return baseRole;
}
坑三:状态同步延迟导致不一致
问题描述:多设备间状态同步存在延迟,导致短时间内各设备状态不一致。
解决方案:实现乐观锁或版本号机制
interface VersionedState {
version: number;
state: any;
deviceId: string;
timestamp: number;
}
private mergeStates(local: VersionedState, remote: VersionedState): VersionedState {
// 使用版本号和设备ID作为冲突解决依据
if (remote.version > local.version) {
return remote;
} else if (remote.version === local.version && remote.timestamp > local.timestamp) {
return remote;
}
return local;
}
HarmonyOS 6适配
新增Continuation分组
HarmonyOS 6支持Continuation分组,可以将不同的功能模块分配到不同设备:
// 定义Continuation分组
const groups: continuationManager.ContinuationGroup[] = [
{
groupId: 'main_display',
abilities: ['MainAbility'],
preferredDeviceType: continuationManager.DeviceType.DEVICE_TYPE_TV
},
{
groupId: 'control_panel',
abilities: ['ControlAbility'],
preferredDeviceType: continuationManager.DeviceType.DEVICE_TYPE_TABLET
},
{
groupId: 'input_method',
abilities: ['InputAbility'],
preferredDeviceType: continuationManager.DeviceType.DEVICE_TYPE_PHONE
}
];
// 注册分组Continuation
await this.continuationManager.registerGroups(groups);
增强的设备能力查询
// 查询设备特定能力
const capabilities = await this.continuationManager.queryDeviceCapabilities(deviceId, [
'screen_size',
'input_methods',
'audio_output',
'camera'
]);
console.info('Device capabilities:', capabilities);
// 输出示例:
// {
// screen_size: { width: 1920, height: 1080 },
// input_methods: ['touch', 'keyboard', 'mouse'],
// audio_output: ['speaker', 'bluetooth'],
// camera: { available: true, resolution: '4K' }
// }
总结
Continuation是HarmonyOS分布式能力的进阶形态,相比Ability迁移,它提供了更灵活的流转粒度和更丰富的协同模式。
核心要点:
- 按需流转:不是全有或全无,可以根据场景选择流转的内容
- 多设备协同:同一应用可以在多个设备上同时运行,各司其职
- 状态同步:通过分布式数据存储实现多设备间状态一致性
- 角色分配:根据设备类型和能力自动分配任务角色
最佳实践:
- 合理设计状态数据结构,确保可序列化和可恢复
- 实现设备角色分配和任务调度逻辑
- 处理设备连接、断开、重连等边界情况
- 使用分布式存储实现状态同步
- 做好冲突检测和解决机制
Continuation打开了多设备协同的大门,让"超级终端"的概念真正落地。下一篇我们将探讨分布式窗口,看看如何实现跨设备的窗口投射。
- 点赞
- 收藏
- 关注作者
评论(0)