一、鸿蒙 Ability 核心概念
1. Ability 定义与分类
Ability 是鸿蒙应用的最小功能单元,分为两类核心类型(FA/PA),对应不同应用场景:
| 类型 | 全称 | 核心作用 | 典型场景 |
|---|---|---|---|
| PageAbility(FA) | Feature Ability | 提供 UI 交互,承载页面展示 | 应用主页面、详情页等可视化界面 |
| ServiceAbility(PA) | Particle Ability | 提供后台服务,无 UI 界面 | 数据同步、音视频播放、网络请求等后台任务 |
2. 核心生命周期详解
(1)PageAbility 生命周期(UI 页面核心)
onCreate():页面创建时调用(初始化数据、绑定组件)
onDestroy():页面销毁时调用(释放资源、取消订阅)
onForeground():页面切换到前台时调用(刷新数据)
onBackground():页面切换到后台时调用(保存状态)
生命周期流程:onCreate() → onForeground() → 运行中 → onBackground() → onDestroy()
(2)ServiceAbility 生命周期(后台服务核心)
onStart():服务创建时调用(仅触发一次)
onCommand():接收其他组件调用请求时触发
onConnect():与其他组件建立连接时调用
onDisconnect():连接断开时调用
onStop():服务销毁时调用(释放后台资源)
3. FA 与 PA 的交互方式
PageAbility 调用 ServiceAbility:通过abilityManager.startAbility()启动服务,通过connectAbility()建立连接
ServiceAbility 向 PageAbility 通信:通过Intent传递数据,或使用事件总线(如Emitter)
二、服务卡片(Widget)开发全流程
服务卡片是鸿蒙特色功能,可在桌面展示核心信息,支持点击跳转 APP,开发需经历「配置→布局→数据绑定→交互实现」四步。
1. 核心配置文件
(1)应用配置文件(config.json)
需在module节点下声明卡片信息,指定卡片元数据路径:
| // config.json{ "module": { "abilities": [ { "name": ".WeatherAbility", // 关联的Ability名称 "type": "page", "visible": true, "widgets": [ { "name": "WeatherWidget", // 卡片名称(需与widget.json一致) "src": "./widgets/WeatherWidget", // 卡片资源路径 "window": { "designWidth": 720, // 设计宽度(适配基准) "autoDesignWidth": true } } ] } ] }} |
|---|
(2)卡片元数据(widget.json)
在widgets/WeatherWidget目录下创建,定义卡片尺寸、更新策略:
| // widgets/WeatherWidget/widget.json{ "name": "WeatherWidget", "description": "天气服务卡片", "author": "HarmonyOS Developer", "version": "1.0.0", "minAPIVersion": 9, "defaultDimension": "21", // 默认尺寸(宽2格×高1格) "supportedDimensions": ["21", "4*2"], // 支持的桌面尺寸 "updateEnabled": true, // 允许数据刷新 "updateDuration": 3600, // 默认刷新间隔(秒),最小30秒 "defaultColorMode": "auto" // 自动适配深色/浅色模式} |
|---|
2. 卡片布局设计(widget.ets)
使用 ArkTS 组件编写卡片 UI,需遵循 “轻量布局” 原则(避免复杂嵌套):
// widgets/WeatherWidget/widget.etsimport router from '@ohos.router';import { FlexAlign, ItemAlign } from '@ohos/ui';@Entry@Componentstruct WeatherWidget { // 卡片数据(通过AppStorage实现全局共享) @Consume weatherData: { city: string; temp: number; condition: string }; build() { Column({ space: 15, alignItems: ItemAlign.Center }) .width('100%') .height('100%') .padding(20) .backgroundColor('#4a6cf7') { // 城市名称 Text(this.weatherData.city) .fontSize(24) .fontWeight(FontWeight.Bold) .fontColor('#ffffff') // 温度与天气状况(水平排列) Row({ space: 20, alignItems: ItemAlign.Center }) { Text(${this.weatherData.temp}℃) .fontSize(36) .fontWeight(FontWeight.Bold) .fontColor('#ffffff') Text(this.weatherData.condition) .fontSize(20) .fontColor('#f0f8ff') } // 点击区域(跳转APP详情页) .onClick(() => { // 卡片点击跳转,指定目标页面 router.pushUrl({ url: 'pages/WeatherDetailPage' }); }) } }} |
|---|
3. 数据刷新实现
服务卡片数据刷新有两种核心方式,本文采用「定时刷新 + 主动更新」结合:
(1)全局数据共享(AppStorage)
在 Ability 中初始化数据并存储到 AppStorage,卡片通过@Consume接收:
| // abilities/WeatherAbility.etsimport AppStorage from '@ohos.appstorage';import { WeatherData } from '../model/WeatherModel';@Entry@Componentstruct WeatherAbility { // 初始化天气数据并写入AppStorage private initWeatherData: WeatherData = { city: '北京', temp: 25, condition: '晴' }; onCreate() { // 将数据存入全局AppStorage,供卡片消费 AppStorage.setOrCreate('weatherData', this.initWeatherData); // 启动定时刷新(模拟实时更新) this.startWeatherRefresh(); } // 定时刷新天气数据(每30分钟更新一次) startWeatherRefresh() { setInterval(() => { // 模拟接口请求获取新数据(实际开发替换为真实接口) const newTemp = this.initWeatherData.temp + Math.floor(Math.random() * 5) - 2; const newCondition = ['晴', '多云', '阴'][Math.floor(Math.random() * 3)]; const updatedData = { ...this.initWeatherData, temp: newTemp, condition: newCondition }; // 更新AppStorage,卡片自动同步 AppStorage.set('weatherData', updatedData); this.initWeatherData = updatedData; }, 30 * 60 * 1000); // 30分钟刷新一次 } build() { // 应用详情页布局(省略,可参考上一篇列表页实现) Column() { Text('天气详情页') .fontSize(32) } .width('100%') .height('100%') }} |
|---|
(2)数据模型定义(WeatherModel.ets)
| // model/WeatherModel.etsexport interface WeatherData { city: string; // 城市名称 temp: number; // 温度(℃) condition: string; // 天气状况(晴/多云/阴等)} |
|---|
4. 卡片点击事件与跳转
卡片中通过onClick绑定事件,使用router.pushUrl跳转至 APP 内页面
需确保目标页面已在main_pages.json中注册:
| // main_pages.json{ "src": [ "pages/WeatherDetailPage" // 天气详情页 ]} |
|---|
三、实战:完整天气服务卡片代码整合
1. 项目目录结构
| src/├── abilities/│ └── WeatherAbility.ets // 主Ability(承载详情页+数据刷新)├── pages/│ └── WeatherDetailPage.ets // 天气详情页├── widgets/│ └── WeatherWidget/│ ├── widget.ets // 卡片布局│ └── widget.json // 卡片元数据├── model/│ └── WeatherModel.ets // 数据模型├── config.json // 应用配置└── main_pages.json // 页面路由配置 |
|---|
2. 关键功能说明
(1)数据同步机制
Ability 通过AppStorage存储天气数据,卡片通过@Consume实时接收更新
定时刷新通过setInterval模拟,实际开发可替换为鸿蒙BackgroundTaskManager实现后台稳定刷新
(2)尺寸适配
widget.json中supportedDimensions声明支持的桌面尺寸(21、42)
布局使用百分比宽度(width('100%'))和弹性布局,确保不同尺寸下显示正常
(3)生命周期联动
Ability 的onCreate初始化数据,onDestroy取消定时任务(避免内存泄漏):
| // WeatherAbility.ets 补充onDestroy方法onDestroy() { // 取消定时刷新任务 clearInterval(this.refreshTimer);} |
|---|
四、常见问题与解决方案
1. 服务卡片不显示
检查config.json中widgets配置路径是否正确(需指向 widget.json 所在目录)
确保widget.json的minAPIVersion与项目编译版本一致
桌面添加卡片时选择对应尺寸(需在supportedDimensions中声明)
2. 数据不刷新
确认updateEnabled为true,且updateDuration不小于 30 秒
复杂数据更新需触发 AppStorage 引用变化,使用扩展运算符:AppStorage.set('weatherData', {...newData})
后台刷新需申请ohos.permission.KEEP_BACKGROUND_RUNNING权限
3. 卡片点击跳转失败
目标页面需在main_pages.json中注册
卡片中router.pushUrl的url路径需与配置一致
确保应用已安装(桌面卡片依赖应用存在)