##Harmony OS Next ##Ark Ts ##教育
本文适用于教育科普行业进行学习,有错误之处请指出我会修改。
🤔 AbilityStage 是啥?
简单说就是每个 Module 的专属管家!当你的 HAP 文件第一次加载时,系统会自动创建这个管家实例,负责 Module 的初始化操作~
💡 关键点:
🔧 手动创建步骤(超简单!)
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 种核心能力,按需取用 ⤵️
🚨 内存优化必看!
系统在后台会缓存应用,但内存不足时会强杀进程! 通过onMemoryLevel()
及时清理资源保命 👇
import { AbilityStage, AbilityConstant } from '@kit.AbilityKit';
export default class MyAbilityStage extends AbilityStage {
onMemoryLevel(level: AbilityConstant.MemoryLevel): void {
// 💥 这里赶紧释放非关键资源!
// 比如:清缓存/关后台任务/卸载组件
}
}
复制代码
💎 举个栗子: 当用户切换多任务时触发该回调,及时释放图片缓存等占内存大户~
⚡️ 总结速查表
🚀 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)
适用场景:每次都要新建的页面(如新建文档/聊天) 效果:
🛠️ 配置方法
{
"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️⃣ 系统自动执行:
📚 场景案例:文档应用
▶️ 打开新文档A → 新建UIAbility实例1(Key=文档A路径)
▶️ 关闭文档A后重新打开 → 新建实例2(原实例已销毁)
▶️ 再打开文档B → 新建实例3(Key=文档B路径)
▶️ 再次打开文档A → **复用实例2**(Key匹配成功!)
复制代码
💎 三种模式速查表
⚡️ 操作口诀
要复用 → 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' } }
})
})
复制代码
🎯 精准启动指定页面
⚡️ 两种启动场景对比表
📌 场景 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' });
}
}
复制代码
生活化案例 📱: 短信应用在后台时,从联系人页点击"发短信"→ 直接唤醒短信应用并跳转到聊天页!
🧹 优雅关闭的两种姿势
💎 核心要点速记表
⚡️ 避坑指南
1️⃣ 跨模块启动记得配 moduleName:"moduleName": "news"
2️⃣ 热启动需在 onWindowStageCreate 中提前缓存 UIContext
3️⃣ 返回结果时 resultCode 必须前后一致!
4️⃣ 多实例模式(multiton)下每次都会创建新实例
复制代码
评论