鸿蒙的"1+8+N"战略喊了很多年,但开发者真正面对的问题是:一套代码怎么在手机、平板、车机、智慧屏、手表上跑得起来?自适应布局只是第一步,真正的挑战在于业务逻辑怎么分层、状态怎么同步、跨设备能力怎么抽象。
这一篇不讲口号,讲工程落地。
一、多端协同的三种模式
实际项目中,跨设备协同通常逃不出三种模式:
三种模式对架构的要求不一样。同构多端要求 UI 层足够灵活;能力互助要求设备发现和能力封装;任务接续要求状态迁移和生命周期管理。
二、同构多端:让 UI 随设备而变
同构多端的核心不是「写死判断」,而是「按能力分层」。推荐的分层结构:
src/main/ets/
├── ability/ # Ability 入口与生命周期
├── pages/ # 页面级组件
├── features/ # 业务功能模块(设备无关)
├── ui/components/ # 可复用 UI 组件
├── ui/adaptive/ # 自适应布局策略
└── device/ # 设备能力封装
业务功能模块(features)应该只依赖抽象的设备能力接口,不直接调用具体设备的 API。比如一个扫码功能,手机用相机,平板也可以用相机,智慧屏可以调用手机的相机能力。
// 设备能力抽象:相机
export interface ICameraService {
capture(): Promise<image.PixelMap>;
isAvailable(): boolean;
}
// 手机/平板本地实现
export class LocalCameraService implements ICameraService {
async capture(): Promise<image.PixelMap> {
// 调用本地 Camera Kit
}
isAvailable(): boolean { return true; }
}
// 智慧屏远端实现:调用已连接手机的相机
export class RemoteCameraService implements ICameraService {
async capture(): Promise<image.PixelMap> {
// 通过 Distributed Service Kit 调用手机相机
}
isAvailable(): boolean { return hasTrustedPhone(); }
}
UI 层根据 ICameraService.isAvailable() 决定是显示拍照按钮,还是提示「请连接手机拍照」。
三、自适应布局:不是 mediaQuery 一把梭
HarmonyOS NEXT 提供了响应式布局能力,比如 breakpoints、gridRow/gridCol、display 等。但好布局的关键不是用了多少响应式 API,而是把布局策略和组件结构解耦。
推荐做法:
按断点定义布局策略:xs(<320dp)、sm(320-600dp)、md(600-840dp)、lg(840-1440dp)、xl(>1440dp)。
组件按布局策略渲染:同一个页面,在手机上单列,在平板双列,在 PC 三列。
避免设备类型判断:判断屏幕尺寸比判断设备类型更稳定。
import { mediaquery } from '@kit.ArkUI';
@Entry
@Component
struct AdaptiveHome {
@State currentBreakpoint: string = 'md';
listener: mediaquery.MediaQueryListener | null = null;
aboutToAppear() {
this.listener = mediaquery.matchMediaSync('(width<600vp)');
this.listener.on('change', (mediaQueryResult) => {
this.currentBreakpoint = mediaQueryResult.matches ? 'sm' : 'lg';
});
}
build() {
if (this.currentBreakpoint === 'sm') {
MobileHome()
} else {
TabletHome()
}
}
}
四、分布式状态:让多设备看见同一份数据
任务接续最难的不是跳转,而是状态一致。用户在手机编辑了一半的文档,到平板上继续,文档内容、光标位置、未保存的修改都要同步。
三种同步策略:
import { distributedKVStore } from '@kit.ArkData';
let kvManager: distributedKVStore.KVManager | null = null;
let kvStore: distributedKVStore.SingleKVStore | null = null;
async function initDistributedData() {
kvManager = distributedKVStore.createKVManager({
bundleName: 'com.example.notes'
});
const options: distributedKVStore.Options = {
createIfMissing: true,
encrypt: false,
backup: false,
autoSync: true,
kvStoreType: distributedKVStore.KVStoreType.DEVICE_COLLABORATION,
securityLevel: distributedKVStore.SecurityLevel.S2
};
kvStore = await kvManager.getKVStore('notes_state', options);
kvStore.on('dataChange', distributedKVStore.SubscribeType.SUBSCRIBE_TYPE_ALL, (data) => {
console.info(`remote data changed: ${JSON.stringify(data)}`);
});
}
分布式数据不是银弹。它适合状态量不大、对一致性要求不高的场景。如果业务数据量大、冲突规则复杂,还是建议走云端同步。
五、任务接续:不只是页面跳转
HarmonyOS NEXT 的 Ability 支持迁移(continue)能力。但迁移不是系统帮你自动完成的,你需要在代码里显式处理:
在
module.json5中声明continuable。在
onContinue()中决定是否允许迁移,以及需要保存哪些数据。在目标设备的
onCreate()/onNewWant()中恢复状态。
import { UIAbility, Want } from '@kit.AbilityKit';
export default class EditorAbility extends UIAbility {
onContinue(want: Want): AbilityConstant.OnContinueResult {
// 把当前编辑状态写入 want 参数
want.parameters = {
draftId: this.currentDraftId,
cursorPosition: this.cursorPosition
};
return AbilityConstant.OnContinueResult.AGREE;
}
onCreate(want: Want): void {
const draftId = want.parameters?.draftId as string;
if (draftId) {
this.restoreDraft(draftId);
}
}
}
六、实战建议:多端项目从三个问题开始
你的应用哪些功能必须跑在哪些设备上? 不是所有功能都适合所有设备。
哪些状态需要跨设备一致? 区分本地状态、设备级状态、用户级状态。
哪些能力可以通过远端设备补齐? 不要假设每个设备都有完整硬件。
把这三个问题回答清楚,多端架构基本不会跑偏。
小结
跨平台与多端协同不是「一套代码打天下」那么简单,而是要在 UI、状态、能力三个维度做合理抽象。同构多端靠响应式布局和能力封装,能力互助靠设备发现与服务抽象,任务接续靠状态迁移和生命周期管理。
下篇进入 AI 原生应用,看看鸿蒙系统级 AI 能力怎么改变应用开发方式。
参考阅读
HarmonyOS 开发者文档:一次开发,多端部署
HarmonyOS 开发者文档:分布式数据管理
HarmonyOS 开发者文档:应用接续开发指南