系列:鸿蒙开发从入门到专家 · 第 86 篇
原子化服务(Atomic Service)是鸿蒙生态里很独特的一种应用形态:免安装、即点即用、以卡片为入口。第 2 批我们已经讲过基础概念,本篇进入进阶话题——卡片与主体的双向通信、分包策略、以及无状态架构下的生命周期管理。这些都是把元服务从 demo 做成可上架产品的关键。
一、元服务的核心结构再回顾
一个元服务通常包含:
EntryAbility:服务入口,用户点击后进入的完整页面。
FormExtensionAbility:卡片扩展能力,负责桌面、负一屏等位置的卡片内容。
ServiceExtensionAbility:后台服务能力,处理不需要 UI 的长时任务或数据同步。
和普通应用相比,元服务最大的不同是"安装 Free"和"生命周期更短"。系统可能随时回收元服务进程,开发者不能假设它一直活着。
二、卡片与主体的双向通信
卡片本身不能执行复杂业务逻辑,它需要和元服务主体通信。通信方式主要有两种:
2.1 卡片点击拉起主体
卡片点击时可以通过 routerEvent 或 messageEvent 触发对应动作。例如点击天气卡片打开详情页:
// WidgetCard.ets
@Entry
@Component
struct WidgetCard {
@StorageProp('formId') formId: string = '';
@StorageProp('cityName') cityName: string = '北京';
build() {
Column() {
Text(`${this.cityName} 天气`)
.fontSize(14)
.fontColor('#666')
Button('查看详情')
.onClick(() => {
postCardAction(this, {
action: 'router',
abilityName: 'EntryAbility',
params: { formId: this.formId, city: this.cityName }
});
})
}
.width('100%')
.height('100%')
.padding(12)
}
}
2.2 主体更新卡片
当后端数据变化时,主体可以主动更新卡片:
import { formProvider, formBindingData } from '@kit.FormKit';
async function updateWeatherCard(formId: string, weather: object) {
const formData = formBindingData.createFormBindingData({
cityName: weather.city,
temperature: `${weather.temp}°C`,
weatherDesc: weather.desc,
updateTime: new Date().toLocaleTimeString()
});
await formProvider.updateForm(formId, formData);
}
2.3 卡片触发主体后台处理
如果卡片需要刷新数据但不想拉起完整页面,可以用 messageEvent:
Button('刷新')
.onClick(() => {
postCardAction(this, {
action: 'message',
abilityName: 'EntryAbility',
params: { action: 'refresh', formId: this.formId }
});
})
主体在 onFormEvent 中接收并处理:
import { FormExtensionAbility, formBindingData } from '@kit.FormKit';
export default class WeatherWidgetAbility extends FormExtensionAbility {
onFormEvent(formId: string, message: string) {
const params = JSON.parse(message);
if (params.action === 'refresh') {
// 请求网络,更新卡片
}
}
}
三、分包策略
元服务对单个包大小有限制:单个 HAP(含依赖的 HSP)不能超过 2MB。超过就需要分包。
3.1 分包原则
首包:Entry HAP,包含首页和启动必需资源。
功能分包:按功能模块拆分,用户用到时再加载。
HSP 共享包:公共代码和资源抽成 HSP,减少重复。
3.2 module.json5 中的关键字段
{
"module": {
"name": "entry",
"type": "atomicService",
"installationFree": true,
"deliveryWithInstall": true,
"dependencies": [
{ "moduleName": "library-common", "bundleName": "com.example.service" }
]
}
}
分包时要注意依赖关系不能形成循环,否则会导致加载失败。建议在项目初期就把公共模块独立出来,而不是等到包体积告警再重构。
四、无状态架构
元服务被系统回收后,内存中的状态会丢失。设计时要避免把重要状态放在全局变量或单例中。
4.1 状态保存到持久化存储
import { preferences } from '@kit.ArkData';
const store = preferences.getPreferencesSync(getContext(), { name: 'service_cache' });
function saveState(key: string, value: object) {
store.putSync(key, JSON.stringify(value));
store.flush();
}
function loadState<T>(key: string): T | undefined {
const raw = store.getSync(key, '') as string;
return raw ? JSON.parse(raw) : undefined;
}
4.2 启动时恢复状态
EntryAbility 的 onCreate 或 onNewWant 中,从持久化存储恢复必要状态,不要依赖内存中的缓存。
import { UIAbility, Want } from '@kit.AbilityKit';
export default class EntryAbility extends UIAbility {
onCreate(want: Want) {
const lastCity = loadState<string>('lastCity') || '北京';
this.processLaunchParams(want, lastCity);
}
}
4.3 避免全局单例
元服务中尽量不要使用全局单例保存业务数据。如果必须共享,使用 AppStorage 或 LocalStorage,并做好空值处理。
五、Want 机制与跨服务调用
元服务之间可以通过 Want 互相拉起,也可以用 openAtomicService 打开其他元服务。
import { common, AtomicServiceOptions, wantConstant } from '@kit.AbilityKit';
async function openPartnerService(context: common.UIAbilityContext, appId: string) {
const options: AtomicServiceOptions = {
flags: wantConstant.Flags.FLAG_INSTALL_ON_DEMAND,
parameters: { source: 'my_service', productId: '12345' }
};
try {
const result = await context.openAtomicService(appId, options);
console.info('open success');
} catch (err) {
console.error(`open failed: ${err.message}`);
}
}
跨服务调用时要注意参数大小限制,建议只传必要 ID,详细数据通过后端或分布式数据服务共享。
六、实战:一个电商秒杀元服务
以"限时秒杀提醒"元服务为例:
用户从桌面卡片看到秒杀倒计时和商品图。
卡片定时向主体请求最新价格和库存。
秒杀开始前 5 分钟,系统通过事件推荐弹出提醒。
用户点击卡片进入 EntryAbility,完成下单或加购。
下单完成后,主体更新卡片状态为"已预约"或"已售罄"。
这个场景里,卡片是流量入口,主体是交易闭环,后台服务负责定时刷新和消息触达。三者边界清楚,才能做出稳定的元服务。
七、小结
原子化服务的进阶重点不是更复杂的 UI,而是"轻、快、稳":轻量包体、快速启动、稳定恢复。卡片与主体的通信、分包策略、无状态架构是三个必须掌握的能力。元服务被回收不可怕,可怕的是回收后用户再进来发现状态丢失、流程断裂。
下一篇我们讨论元服务的商业化路径,看看如何从"有意思"变成"有收入"。
参考阅读
华为开发者联盟:原子化服务开发指南
华为开发者联盟:Form Kit 开发指南
华为开发者联盟:Ability Kit 开发指南