鸿蒙技术干货3: Ability 组件详解,FA/PA 与服务卡片开发

1 阅读5分钟

一、鸿蒙 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路径需与配置一致

确保应用已安装(桌面卡片依赖应用存在)

加入班级,一起学习鸿蒙开发