《HarmonyOSNext终极UIAbility手册:从启动模式到页面跳转,一网打尽!》
《HarmonyOSNext终极UIAbility手册:从启动模式到页面跳转,一网打尽!》
##Harmony OS Next ##Ark Ts ##教育
本文适用于教育科普行业进行学习,有错误之处请指出我会修改。
🤔 AbilityStage是啥?
简单说就是每个Module的专属管家!当你的HAP文件第一次加载时,系统会自动创建这个管家实例,负责Module的初始化操作~
💡 关键点:
- 🫶 一对一关系:1个Module = 1个AbilityStage
- ⚠️ 默认不生成:DevEco Studio不会自动创建,得自己动手!
🔧 手动创建步骤(超简单!)
1️⃣ 右键点击Module的ets目录 → New > Directory → 新建文件夹命名为`myabilitystage`
2️⃣ 右键点击myabilitystage → New > ArkTS File → 新建文件`MyAbilityStage.ets`
3️⃣ 写入核心代码 ↓↓↓
import { AbilityStage, Want } from '@kit.AbilityKit';
export default class MyAbilityStage extends AbilityStage {
onCreate(): void {
// 💫 首次加载时触发!搞初始化最合适(比如加载资源/开线程)
}
onAcceptWant(want: Want): string {
// 🎯 仅specified模式触发!
return 'MyAbilityStage';
}
}
⚙️ 配置文件别漏啦!
在module.json5
里加个入口声明,否则不生效!
{
"module": {
"name": "entry",
"type": "entry",
"srcEntry": "./ets/myabilitystage/MyAbilityStage.ets", // 🚨重点在这里!
// ...
}
}
⏳ 生命周期回调大全
AbilityStage有4种核心能力,按需取用 ⤵️
回调函数 🎛️ | 触发场景 🔥 | 典型用途 💼 |
---|---|---|
onCreate() | Module首次加载时 | 初始化资源/线程 ✨ |
onAcceptWant() | specified模式启动UIAbility | 特殊启动逻辑定制 ⚡️ |
onConfigurationUpdated() | 系统配置变更(语言/深色模式等) | 动态适配新配置 🌓 |
onMemoryLevel() | 系统内存不足时 | 紧急释放资源 🆘 |
🚨 内存优化必看!
系统在后台会缓存应用,但内存不足时会强杀进程! 通过onMemoryLevel()
及时清理资源保命 👇
import { AbilityStage, AbilityConstant } from '@kit.AbilityKit';
export default class MyAbilityStage extends AbilityStage {
onMemoryLevel(level: AbilityConstant.MemoryLevel): void {
// 💥 这里赶紧释放非关键资源!
// 比如:清缓存/关后台任务/卸载组件
}
}
💎 举个栗子: 当用户切换多任务时触发该回调,及时释放图片缓存等占内存大户~
⚡️ 总结速查表
操作 | 注意要点 |
---|---|
创建AbilityStage | 手动建文件+继承类 |
声明入口 | module.json5 中写对srcEntry 路径 |
内存紧急处理 | onMemoryLevel() 里做资源回收 |
特殊启动模式 | onAcceptWant() 只在specified模式生效 |
🚀 UIAbility启动模式三剑客
应用不同场景,系统给你三种选择: 1️⃣ singleton(单实例模式)→ 全家共用1个实例 2️⃣ multiton(多实例模式)→ 每次新建1个实例 3️⃣ specified(指定实例模式)→ 自由控制实例匹配
⚠️ 冷知识:
multiton
原名standard
,效果完全一样,代码里看到别懵!
🎯 1. 单实例模式(singleton)
适用场景:全局只允许存在1个的应用(如设置页) 默认效果:
- 无论调用多少次
startAbility()
- 系统中永远只有唯一UIAbility实例
- 任务栏中也只显示1个!
graph LR
A[调用startAbility] --> B{实例存在?}
B --✅存在--> C[复用原实例] --> D[触发onNewWant回调]
B --❌不存在--> E[创建新实例]
🛠️ 配置方法(module.json5)
{
"abilities": [
{
"launchType": "singleton" //✨ 加上这行!
}
]
}
🧩 2. 多实例模式(multiton)
适用场景:每次都要新建的页面(如新建文档/聊天) 效果:
- 每次
startAbility()
都创建全新实例 - 任务栏可显示多个相同Ability figures/multiton-mode-demo.png
🛠️ 配置方法
{
"abilities": [
{
"launchType": "multiton" //💥 改这里!
}
]
}
🔍 3. 指定实例模式(specified)
适用场景:既要新建实例又要复用实例(如文档类应用) 核心原理:
sequenceDiagram
调用方->>AbilityStage: startAbility(带Key参数)
AbilityStage->>系统: onAcceptWant()返回匹配Key
系统->>UIAbility: { 匹配成功?复用 : 新建 }
🛠️ 配置四步走:
STEP 1️⃣ 声明specified模式
{
"abilities": [
{
"launchType": "specified" //🎯 必改!
}
]
}
STEP 2️⃣ 调用时传入唯一Key
// 启动时携带自定义Key(如文档路径)
context.startAbility({
bundleName: 'com.example.app',
parameters: { instanceKey: '文档A路径' } //📍 关键标识!
})
STEP 3️⃣ AbilityStage中设置匹配规则
export default class MyAbilityStage extends AbilityStage {
onAcceptWant(want: Want): string {
// 🧩 根据传入Key返回匹配标识
return `UIAbility_${want.parameters.instanceKey}`;
}
}
STEP 4️⃣ 系统自动执行:
匹配结果 | 系统行为 | 生命周期 |
---|---|---|
✅ Key匹配 | 复用原有UIAbility实例 | 触发onNewWant() |
❌ 无匹配 | 创建新UIAbility实例 | 触发**onCreate()**等回调 |
📚 场景案例:文档应用
▶️ 打开新文档A → 新建UIAbility实例1(Key=文档A路径)
▶️ 关闭文档A后重新打开 → 新建实例2(原实例已销毁)
▶️ 再打开文档B → 新建实例3(Key=文档B路径)
▶️ 再次打开文档A → **复用实例2**(Key匹配成功!)
💎 三种模式速查表
模式 | 配置文件 | 实例数量 | 典型场景 | 生命周期变化 |
---|---|---|---|---|
singleton | launchType: singleton |
1个 | 设置页/用户中心 | 复用→只触发onNewWant |
multiton | launchType: multiton |
多个 | 新建文档/聊天窗口 | 每次新建触发完整生命周期 |
specified | launchType: specified |
动态控制 | 文档复用/特定实例重开 | 匹配成功→只触发onNewWant |
⚡️ 操作口诀
要复用 → singleton
总要新 → multiton
灵活控 → specified + Key匹配
搞定!现在连文档小白都能秒懂启动模式啦 🎉以下是根据您需求全面优化的文本,保留所有技术细节但采用活泼口语化风格,融入表情符号、分段标题和总结表格:
🚀 UIAbility启动全攻略
一句话科普: UIAbility是系统调度的最小单元!应用内跳转、跨应用启动(比如调支付)都靠它~
📦 基础启动三步走
场景:从EntryAbility启动FuncAbility
graph LR
A[EntryAbility] --携带参数--> B((startAbility)) --> C[FuncAbility]
🛠️ 调用方代码示例
@Entry
@Component
struct Page_UIAbilityComponentsInteractive {
private context = getContext(this) as common.UIAbilityContext;
build() {
Column() {
Button('启动FuncAbility')
.onClick(() => {
// 🧩 关键参数配置
let wantInfo: Want = {
bundleName: 'com.example.app',
abilityName: 'FuncAbilityA',
parameters: { info: '传递的数据' } // 自定义参数
};
// ✨ 核心启动方法
this.context.startAbility(wantInfo).then(() => {
console.log('启动成功!');
}).catch((error) => {
console.error('启动失败:', error);
});
})
}
}
}
📥 接收方获取数据
// FuncAbilityA.ts
export default class FuncAbilityA extends UIAbility {
onCreate(want: Want) {
// 💡 获取传递的参数
const receivedData = want.parameters?.info;
console.log('收到数据:', receivedData);
}
}
🔄 带返回结果的启动(超实用!)
场景:启动登录UIAbility后获取登录结果
📤 调用方发送请求 + 接收结果
// EntryAbility中
Button('登录并获取结果')
.onClick(() => {
const RESULT_CODE = 1001; // 约定好的结果码
const context = getContext(this) as common.UIAbilityContext;
context.startAbilityForResult({
bundleName: 'com.example.app',
abilityName: 'LoginAbility'
}).then((data) => {
// ✅ 结果匹配校验
if (data?.resultCode === RESULT_CODE) {
const token = data.want?.parameters?.token;
console.log('登录凭证:', token);
}
})
})
📥 目标方返回结果
// LoginAbility中
Button('完成登录')
.onClick(() => {
const RESULT_CODE = 1001;
const context = getContext(this) as common.UIAbilityContext;
// ✨ 核心返回方法
context.terminateSelfWithResult({
resultCode: RESULT_CODE,
want: { parameters: { token: '用户Token' } }
})
})
🎯 精准启动指定页面
⚡️ 两种启动场景对比表
启动类型 | 特点 | 生命周期触发 |
---|---|---|
冷启动 ❄️ | UIAbility完全关闭 | onCreate → onWindowStageCreate |
热启动 🔥 | UIAbility已在后台运行 | 直接触发onNewWant |
📌 场景1:冷启动指定页面
调用方传递标识
context.startAbility({
bundleName: 'com.example.app',
abilityName: 'NewsAbility',
parameters: { router: 'sports' } // 🎯 页面标识
})
接收方处理逻辑
// NewsAbility.ts
export default class NewsAbility extends UIAbility {
funcAbilityWant: Want | undefined;
onCreate(want: Want) {
this.funcAbilityWant = want; // 暂存参数
}
onWindowStageCreate(windowStage) {
// 🧭 根据标识跳转不同页面
let targetPage = 'pages/Index';
if (this.funcAbilityWant?.parameters?.router === 'sports') {
targetPage = 'pages/SportsNews';
}
windowStage.loadContent(targetPage);
}
}
📌 场景2:热启动指定页面(已运行实例)
关键:UIContext动态跳转
// NewsAbility.ts中
uiContext: UIContext | undefined; // 声明UI上下文
onWindowStageCreate(windowStage) {
windowStage.getMainWindow((err, window) => {
this.uiContext = window.getUIContext(); // 🔑 获取上下文
})
}
onNewWant(want: Want) {
// 🔥 热启动时触发
if (want.parameters?.router === 'tech') {
this.uiContext?.getRouter().pushUrl({ url: 'pages/TechNews' });
}
}
生活化案例 📱: 短信应用在后台时,从联系人页点击"发短信"→ 直接唤醒短信应用并跳转到聊天页!
🧹 优雅关闭的两种姿势
方法 | 效果 | 代码示例 |
---|---|---|
terminateSelf() |
关闭当前实例(保留快照) | context.terminateSelf() |
terminateSelfWithResult() |
关闭+返回结果 | 见上方案例 |
killAllProcesses() |
关闭所有UIAbility实例 | 应用上下文调用 |
💎 核心要点速记表
场景 | 核心API | 注意要点 |
---|---|---|
基础启动 | startAbility() |
用Want传递参数 |
带返回值启动 | startAbilityForResult() |
需约定结果码(resultCode) |
冷启动指定页面 | windowStage.loadContent() |
在onWindowStageCreate处理 |
热启动指定页面 | uiContext.getRouter() |
需提前获取UIContext |
关闭当前实例 | terminateSelf() |
默认保留最近任务列表快照 |
⚡️ 避坑指南
1️⃣ 跨模块启动记得配 moduleName:"moduleName": "news"
2️⃣ 热启动需在 onWindowStageCreate 中提前缓存 UIContext
3️⃣ 返回结果时 resultCode 必须前后一致!
4️⃣ 多实例模式(multiton)下每次都会创建新实例
- 0回答
- 0粉丝
- 0关注
- 一、HarmonyOS Next 开发者手册项目之项目架构设计
- OpenHarmony: 如何通过路由跳转到一个只有页面没有UIAbility的模块
- HarmonyOSNext网格布局开发全攻略:从九宫格到跨屏动画的终极实践指南》
- Harmony OS Next《ArkUI全组件终极指南 | 从布局到交互一站式精通》
- 鸿蒙Navigation处理启动页跳转到首页问题
- 如何跳转到权限设置页面
- 手把手教你用 Ark-TS UI 做一个会 “动” 的计数器:从代码到原理全解析
- 从零到一:flutter_timezone库的鸿蒙适配深度探索
- 《HarmonyOSNext超全开发指南:UIAbility组件与跨端协作完全解析》
- OpenHarmony: 如何实现跨模块的页面跳转功能
- 从0到1上架一个元服务的全流程
- HarmonyOSNext全栈数据存储双星解析:轻量级VS关系型存储终极指南
- 鸿蒙5网页开发神器 ArkWeb:让 Web 和原生手拉手跳舞
- 鸿蒙5网页开发神器 ArkWeb:让 Web 和原生手拉手跳舞
- 【HarmonyOS 5】鸿蒙中的UIAbility详解(一)