《HarmonyOSNext终极UIAbility手册:从启动模式到页面跳转,一网打尽!》

2025-06-07 11:04:03
108次阅读
0个评论

《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完全关闭 onCreateonWindowStageCreate
热启动 🔥 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)下每次都会创建新实例
收藏00

登录 后评论。没有帐号? 注册 一个。