第5章 图解harmonyos Ability 基础知识
HarmonyOS 学习系统 | 阶段二:进阶实战期
建议学习时长:2-3 周
学习目标
| 序号 | 能力 |
|---|---|
| 1 | 深入理解 FA(Feature Ability) 和 PA(Particle Ability) 的区别与使用场景 |
| 2 | 掌握 Page Ability 完整生命周期及各回调的触发时机 |
| 3 | 理解 Intent 机制,能实现同 Page 和跨 Page 导航 |
| 4 | 了解 Service Ability 和 Data Ability 的基本用法 |
核心图解
内容讲解
5.1 FA 与 PA 概述
如果把一个 HarmonyOS 应用比作一家公司,那么 Ability 就是公司里的不同部门:
- FA(Feature Ability)= 前台部门(销售部、客服部)——直接跟客户(用户)打交道,有"店面"(UI 界面)
- PA(Particle Ability)= 后台部门(仓库部、财务部)——在幕后默默工作,不跟客户直接接触,没有"店面"(无 UI)
- Page Ability= 销售部里的一个柜台——每个柜台(AbilitySlice)展示不同的商品
- Service Ability= 仓库部——后台持续运行,比如音乐播放、文件下载
- Data Ability= 档案室——对外提供数据查询服务,其他部门可以来借阅资料
- Intent= 部门间的调动函——告诉你"去哪个部门、找谁、带什么资料"
Ability 是 HarmonyOS 应用所具备能力的抽象。一个应用可以包含多个 Ability,每个 Ability 实现特定的业务功能。Ability 主要分为 FA 和 PA 两大类。
| 类型 | 全称 | 子类型 | 说明 | 典型场景 |
|---|---|---|---|---|
| FA | Feature Ability | Page Ability | 有 UI 界面,用于与用户交互 | 商品列表、详情页、登录页 |
| PA | Particle Ability | Service Ability | 无 UI,后台运行任务 | 音乐播放、文件下载、数据同步 |
| PA | Particle Ability | Data Ability | 无 UI,提供数据访问抽象 | 数据库操作、文件读写、共享数据 |
5.2 Page Ability 详解
Page 与 AbilitySlice 的关系
一个 Page(即 Page Ability)可以包含一个或多个 AbilitySlice。AbilitySlice 是应用的单个页面及其控制逻辑的总和。当一个 Page 由多个 AbilitySlice 构成时,这些 AbilitySlice 提供的业务能力应具有高度相关性。
路由配置:Page 进入前台时默认只能展示一个 AbilitySlice,通过以下方式配置:
publicclassMainAbilityextendsAbility{@OverridepublicvoidonStart(Intentintent){super.onStart(intent);// 设置默认展示的 AbilitySlicesuper.setMainRoute(MainAbilitySlice.class.getName());// 添加附加路由(可选)addActionRoute("action.pay",PayAbilitySlice.class.getName());}}5.3 Page Ability 生命周期
Page 的生命周期包含以下状态和回调:
| 回调方法 | 触发时机 | 调用次数 | 典型操作 |
|---|---|---|---|
onStart() | Page 首次创建 | 仅一次 | setMainRoute(), 初始化数据 |
onActive() | Page 进入前台可交互 | 多次 | 恢复动画、刷新数据 |
onInactive() | Page 失去焦点 | 多次 | 暂停动画、保存状态 |
onBackground() | Page 进入后台不可见 | 多次 | 释放资源、停止定时器 |
onForeground() | Page 从后台回前台 | 多次 | 重新加载数据 |
onStop() | Page 被销毁 | 仅一次 | 释放所有资源 |
状态转换流程:
UNINITIALIZED → onStart() → INITIAL → onActive() → INACTIVE → onActive() → ACTIVE ↓ ACTIVE → onInactive() → INACTIVE → onBackground() → BACKGROUND → onForeground() → INACTIVE → onActive() → ACTIVE INITIAL → onStop() → DESTROYED关键区别:onStart()仅在 Page 首次创建时调用一次,而onActive()每次从后台回到前台都会调用。数据初始化应放在onStart()中,UI 刷新放在onActive()中。
AbilitySlice 生命周期
AbilitySlice 生命周期回调与 Page 类似,但有以下区别:
onStart()中必须调用setUIContent()加载布局- 同一 Page 内的 AbilitySlice 导航使用
present()/presentForResult() - 返回上一个 AbilitySlice 使用
terminate()
5.4 Service Ability
Service Ability 用于提供后台运行任务的能力,没有 UI 界面。其他 Ability 可以通过startAbility()或connectAbility()来启动或连接 Service Ability。
启动方式
// 启动 Service Ability(一次性操作)IntentserviceIntent=newIntent();Operationoperation=newIntent.OperationBuilder().withDeviceId("").withBundleName("com.example.myapp").withAbilityName("MyServiceAbility").build();serviceIntent.setOperation(operation);startAbility(serviceIntent);连接方式(获取远程代理对象)
// 连接 Service AbilityconnectAbility(serviceIntent,newIAbilityConnection(){@OverridepublicvoidonAbilityConnectDone(ElementNameelementName,IRemoteObjectremoteObject){// 获取远程对象,进行跨进程通信}@OverridepublicvoidonAbilityDisconnectDone(ElementNameelementName){// 连接断开回调}});5.5 Intent 机制
Intent 是 HarmonyOS 应用中不同 Ability 之间传递信息和执行操作的"信使"。它承载了"要做什么"和"怎么做"的信息。
Intent 的核心组成
Intentintent=newIntent();// 设置 Action(动作标识)intent.setAction("action.pay");// 设置 Entity(附加信息)intent.setEntity("entity.default");// 设置参数intent.setParam("amount",100);intent.setParam("orderId","20240101001");// 构建 Operation(目标地址)Operationoperation=newIntent.OperationBuilder().withDeviceId("")// 设备ID(空字符串表示本地).withBundleName("com.example.myapp")// 目标应用包名.withAbilityName("PayAbility")// 目标 Ability 名.withAction("action.pay")// 或通过 Action 匹配.build();intent.setOperation(operation);同 Page 内导航 vs 跨 Page 导航
| 导航类型 | API | 条件 | 返回结果 |
|---|---|---|---|
| 同 Page 内 | present()/presentForResult() | 同一个 Page 下的 AbilitySlice | onResult()回调 |
| 跨 Page | startAbility()/startAbilityForResult() | 不同 Page 的 Ability | onAbilityResult()回调 |
代码速查卡
| API | 功能 | 示例 |
|---|---|---|
setMainRoute() | 设置默认路由 | super.setMainRoute(MainAbilitySlice.class.getName()) |
addActionRoute() | 添加附加路由 | addActionRoute("action.pay", PaySlice.class.getName()) |
present() | 同 Page 导航 | present(new Intent(), Intent.FLAG_ABILITYSLICE_MULTI_DEVICE) |
presentForResult() | 带返回结果导航 | presentForResult(intent, REQUEST_CODE) |
startAbility() | 启动其他 Ability | startAbility(intent) |
startAbilityForResult() | 带返回结果启动 | startAbilityForResult(intent, REQUEST_CODE) |
connectAbility() | 连接 Service | connectAbility(intent, connection) |
terminate() | 关闭当前 AbilitySlice | terminate() |
setResult() | 设置返回结果 | setResult(intent) |
与 Android/iOS 对比
| HarmonyOS Page | Android Activity | iOS ViewController |
|---|---|---|
onStart() | onCreate() | viewDidLoad() |
onActive() | onResume() | viewWillAppear() |
onInactive() | onPause() | viewWillDisappear() |
onBackground() | onStop() | - |
onForeground() | onRestart() | - |
onStop() | onDestroy() | deinit / viewDidDisappear |
Intent | Intent | UIStoryboardSegue |
AbilitySlice | Fragment | Child ViewController |
⚠️ 踩坑回忆录
第一次做页面跳转时,我直接用present()试图跳到另一个 Page 的 AbilitySlice,结果怎么都跳不过去。查了半天文档才明白:present() 只能在同一个 Page 内的 AbilitySlice 之间导航。要跳到另一个 Page,必须用startAbility(),而且还需要在 Intent 中设置 Action 或指定 bundleName + AbilityName。
还有一个坑:onStart()只在 Page 首次创建时调用一次,而onActive()每次从后台回到前台都会调用。我一开始把数据初始化放在了onActive()里,导致每次切回应用都会重新加载数据,体验很差。后来把初始化挪到了onStart(),onActive()只做 UI 刷新,问题才解决。
必做实操任务
| 序号 | 任务 | 难度 |
|---|---|---|
| 1 | 创建包含两个 AbilitySlice 的应用,实现同 Page 内导航 | ★★☆ |
| 2 | 实现 Ability 生命周期回调,在每个回调中打印日志并观察触发顺序 | ★★☆ |
| 3 | 使用 Intent 传递数据到目标 AbilitySlice 并显示 | ★★★ |
| 4 | 创建一个 Service Ability,实现后台计时功能 | ★★★ |
| 5 | 使用startAbilityForResult()实现页面间数据回传 | ★★★ |
学习检查清单
- 能区分 FA 和 PA 的使用场景
- 能说出 Page Ability 完整生命周期的 6 个状态和 6 个回调
- 能使用 Intent 实现同 Page 和跨 Page 导航
- 理解 onStart() 和 onActive() 的区别
- 能说出 Service Ability 的两种启动方式(start / connect)
- 能解释 ActionRoute 的配置方法
- 了解 Data Ability 的基本概念和 URI 访问方式
进阶方向
- 学习 Data Ability 的 CRUD 操作实现
- 了解跨进程通信(IPC)的原理
- 实现一个完整的 Service Ability 音乐播放器