启动模式与实例管理:singleton、multiton 与 specified 场景

主题关键词:launchType、singleton、multiton、specified、onNewWant、实例管理。

封面

文章导读

  • 适合读者:已经会创建 HarmonyOS 工程,但对 AbilityKit 工程边界、生命周期和系统能力衔接不够清晰的开发者。
  • 本篇场景:通知、桌面图标、外部链接多入口同时打开同一个应用时,控制 Ability 实例数量和参数刷新。
  • 本篇结论:启动模式决定系统如何复用 Ability 实例;选错模式会导致页面重复、参数丢失或任务栈混乱。
  • 阅读方式:先看每节配图,再复制关键代码,最后用验收清单检查自己的项目。

目录

  1. 明确本节目标
  2. 理解官方概念
  3. 建立最小工程结构
  4. 声明 Ability 配置
  5. 实现生命周期入口
  6. 加载 ArkUI 页面
  7. 传递业务参数
  8. 读取 Context 能力
  9. 处理前后台切换
  10. 处理重复启动
  11. 处理异常兜底
  12. 释放页面资源
  13. 补充工程封装
  14. 本节小结与练习

1. 明确本节目标

图 7-1:明确本节目标

场景定位

本节把 明确本节目标 放到「通知、桌面图标、外部链接多入口同时打开同一个应用时,控制 Ability 实例数量和参数刷新」这个真实开发场景里理解。它不是孤立 API,而是围绕 启动模式决定系统如何复用 Ability 实例;选错模式会导致页面重复、参数丢失或任务栈混乱。 展开的一个工程动作。当前关注点是 launchType,读者可以把它当成排查 AbilityKit 项目问题时的一条检查线。

实战代码

import UIAbility from '@ohos.app.ability.UIAbility';
import Want from '@ohos.app.ability.Want';

export default class DetailAbility extends UIAbility {
  private currentId = '';

  onCreate(want: Want): void {
    this.applyWant(want, 'create');
  }

  onNewWant(want: Want): void {
    this.applyWant(want, 'new-want');
  }

  private applyWant(want: Want, source: string): void {
    const id = String(want.parameters?.id ?? '');
    if (id && id !== this.currentId) {
      this.currentId = id;
      console.info(`[DetailAbility] ${source}, switch to id=${id}`);
    }
  }
}

代码解释

  1. 入口层只处理系统回调、上下文获取和启动协议,不把页面 UI 细节塞进 Ability。
  2. 业务参数要先校验再使用,尤其是来自通知、外部链接、卡片或跨 Ability 跳转的参数。
  3. 生命周期回调里必须区分“初始化一次”“每次回前台都执行”“退出时释放”三类动作。
  4. 日志要带上业务标识,例如 routeId、taskId、target,方便真机调试时定位问题。

常见坑

使用 singleton 后只处理 onCreate,不处理 onNewWant,第二次打开同一 Ability 时页面仍显示旧数据。

验收标准

  • 能说清 launchType 在 启动模式与实例管理 中承担的职责。
  • 代码能放进 DevEco Studio 工程中按小步验证,而不是只停留在伪代码。
  • 异常分支、生命周期切换和资源释放都有明确处理点。

2. 理解官方概念

图 7-2:理解官方概念

场景定位

本节把 理解官方概念 放到「通知、桌面图标、外部链接多入口同时打开同一个应用时,控制 Ability 实例数量和参数刷新」这个真实开发场景里理解。它不是孤立 API,而是围绕 启动模式决定系统如何复用 Ability 实例;选错模式会导致页面重复、参数丢失或任务栈混乱。 展开的一个工程动作。当前关注点是 singleton,读者可以把它当成排查 AbilityKit 项目问题时的一条检查线。

实战代码

import UIAbility from '@ohos.app.ability.UIAbility';
import Want from '@ohos.app.ability.Want';

export default class DetailAbility extends UIAbility {
  private currentId = '';

  onCreate(want: Want): void {
    this.applyWant(want, 'create');
  }

  onNewWant(want: Want): void {
    this.applyWant(want, 'new-want');
  }

  private applyWant(want: Want, source: string): void {
    const id = String(want.parameters?.id ?? '');
    if (id && id !== this.currentId) {
      this.currentId = id;
      console.info(`[DetailAbility] ${source}, switch to id=${id}`);
    }
  }
}

代码解释

  1. 入口层只处理系统回调、上下文获取和启动协议,不把页面 UI 细节塞进 Ability。
  2. 业务参数要先校验再使用,尤其是来自通知、外部链接、卡片或跨 Ability 跳转的参数。
  3. 生命周期回调里必须区分“初始化一次”“每次回前台都执行”“退出时释放”三类动作。
  4. 日志要带上业务标识,例如 routeId、taskId、target,方便真机调试时定位问题。

常见坑

使用 singleton 后只处理 onCreate,不处理 onNewWant,第二次打开同一 Ability 时页面仍显示旧数据。

验收标准

  • 能说清 singleton 在 启动模式与实例管理 中承担的职责。
  • 代码能放进 DevEco Studio 工程中按小步验证,而不是只停留在伪代码。
  • 异常分支、生命周期切换和资源释放都有明确处理点。

3. 建立最小工程结构

图 7-3:建立最小工程结构

场景定位

本节把 建立最小工程结构 放到「通知、桌面图标、外部链接多入口同时打开同一个应用时,控制 Ability 实例数量和参数刷新」这个真实开发场景里理解。它不是孤立 API,而是围绕 启动模式决定系统如何复用 Ability 实例;选错模式会导致页面重复、参数丢失或任务栈混乱。 展开的一个工程动作。当前关注点是 multiton,读者可以把它当成排查 AbilityKit 项目问题时的一条检查线。

实战代码

import UIAbility from '@ohos.app.ability.UIAbility';
import Want from '@ohos.app.ability.Want';

export default class DetailAbility extends UIAbility {
  private currentId = '';

  onCreate(want: Want): void {
    this.applyWant(want, 'create');
  }

  onNewWant(want: Want): void {
    this.applyWant(want, 'new-want');
  }

  private applyWant(want: Want, source: string): void {
    const id = String(want.parameters?.id ?? '');
    if (id && id !== this.currentId) {
      this.currentId = id;
      console.info(`[DetailAbility] ${source}, switch to id=${id}`);
    }
  }
}

代码解释

  1. 入口层只处理系统回调、上下文获取和启动协议,不把页面 UI 细节塞进 Ability。
  2. 业务参数要先校验再使用,尤其是来自通知、外部链接、卡片或跨 Ability 跳转的参数。
  3. 生命周期回调里必须区分“初始化一次”“每次回前台都执行”“退出时释放”三类动作。
  4. 日志要带上业务标识,例如 routeId、taskId、target,方便真机调试时定位问题。

常见坑

使用 singleton 后只处理 onCreate,不处理 onNewWant,第二次打开同一 Ability 时页面仍显示旧数据。

验收标准

  • 能说清 multiton 在 启动模式与实例管理 中承担的职责。
  • 代码能放进 DevEco Studio 工程中按小步验证,而不是只停留在伪代码。
  • 异常分支、生命周期切换和资源释放都有明确处理点。

4. 声明 Ability 配置

图 7-4:声明 Ability 配置

场景定位

本节把 声明 Ability 配置 放到「通知、桌面图标、外部链接多入口同时打开同一个应用时,控制 Ability 实例数量和参数刷新」这个真实开发场景里理解。它不是孤立 API,而是围绕 启动模式决定系统如何复用 Ability 实例;选错模式会导致页面重复、参数丢失或任务栈混乱。 展开的一个工程动作。当前关注点是 specified,读者可以把它当成排查 AbilityKit 项目问题时的一条检查线。

实战代码

import UIAbility from '@ohos.app.ability.UIAbility';
import Want from '@ohos.app.ability.Want';

export default class DetailAbility extends UIAbility {
  private currentId = '';

  onCreate(want: Want): void {
    this.applyWant(want, 'create');
  }

  onNewWant(want: Want): void {
    this.applyWant(want, 'new-want');
  }

  private applyWant(want: Want, source: string): void {
    const id = String(want.parameters?.id ?? '');
    if (id && id !== this.currentId) {
      this.currentId = id;
      console.info(`[DetailAbility] ${source}, switch to id=${id}`);
    }
  }
}

代码解释

  1. 入口层只处理系统回调、上下文获取和启动协议,不把页面 UI 细节塞进 Ability。
  2. 业务参数要先校验再使用,尤其是来自通知、外部链接、卡片或跨 Ability 跳转的参数。
  3. 生命周期回调里必须区分“初始化一次”“每次回前台都执行”“退出时释放”三类动作。
  4. 日志要带上业务标识,例如 routeId、taskId、target,方便真机调试时定位问题。

常见坑

使用 singleton 后只处理 onCreate,不处理 onNewWant,第二次打开同一 Ability 时页面仍显示旧数据。

验收标准

  • 能说清 specified 在 启动模式与实例管理 中承担的职责。
  • 代码能放进 DevEco Studio 工程中按小步验证,而不是只停留在伪代码。
  • 异常分支、生命周期切换和资源释放都有明确处理点。

5. 实现生命周期入口

图 7-5:实现生命周期入口

场景定位

本节把 实现生命周期入口 放到「通知、桌面图标、外部链接多入口同时打开同一个应用时,控制 Ability 实例数量和参数刷新」这个真实开发场景里理解。它不是孤立 API,而是围绕 启动模式决定系统如何复用 Ability 实例;选错模式会导致页面重复、参数丢失或任务栈混乱。 展开的一个工程动作。当前关注点是 onNewWant,读者可以把它当成排查 AbilityKit 项目问题时的一条检查线。

实战代码

import UIAbility from '@ohos.app.ability.UIAbility';
import Want from '@ohos.app.ability.Want';

export default class DetailAbility extends UIAbility {
  private currentId = '';

  onCreate(want: Want): void {
    this.applyWant(want, 'create');
  }

  onNewWant(want: Want): void {
    this.applyWant(want, 'new-want');
  }

  private applyWant(want: Want, source: string): void {
    const id = String(want.parameters?.id ?? '');
    if (id && id !== this.currentId) {
      this.currentId = id;
      console.info(`[DetailAbility] ${source}, switch to id=${id}`);
    }
  }
}

代码解释

  1. 入口层只处理系统回调、上下文获取和启动协议,不把页面 UI 细节塞进 Ability。
  2. 业务参数要先校验再使用,尤其是来自通知、外部链接、卡片或跨 Ability 跳转的参数。
  3. 生命周期回调里必须区分“初始化一次”“每次回前台都执行”“退出时释放”三类动作。
  4. 日志要带上业务标识,例如 routeId、taskId、target,方便真机调试时定位问题。

常见坑

使用 singleton 后只处理 onCreate,不处理 onNewWant,第二次打开同一 Ability 时页面仍显示旧数据。

验收标准

  • 能说清 onNewWant 在 启动模式与实例管理 中承担的职责。
  • 代码能放进 DevEco Studio 工程中按小步验证,而不是只停留在伪代码。
  • 异常分支、生命周期切换和资源释放都有明确处理点。

6. 加载 ArkUI 页面

图 7-6:加载 ArkUI 页面

场景定位

本节把 加载 ArkUI 页面 放到「通知、桌面图标、外部链接多入口同时打开同一个应用时,控制 Ability 实例数量和参数刷新」这个真实开发场景里理解。它不是孤立 API,而是围绕 启动模式决定系统如何复用 Ability 实例;选错模式会导致页面重复、参数丢失或任务栈混乱。 展开的一个工程动作。当前关注点是 实例管理,读者可以把它当成排查 AbilityKit 项目问题时的一条检查线。

实战代码

import UIAbility from '@ohos.app.ability.UIAbility';
import Want from '@ohos.app.ability.Want';

export default class DetailAbility extends UIAbility {
  private currentId = '';

  onCreate(want: Want): void {
    this.applyWant(want, 'create');
  }

  onNewWant(want: Want): void {
    this.applyWant(want, 'new-want');
  }

  private applyWant(want: Want, source: string): void {
    const id = String(want.parameters?.id ?? '');
    if (id && id !== this.currentId) {
      this.currentId = id;
      console.info(`[DetailAbility] ${source}, switch to id=${id}`);
    }
  }
}

代码解释

  1. 入口层只处理系统回调、上下文获取和启动协议,不把页面 UI 细节塞进 Ability。
  2. 业务参数要先校验再使用,尤其是来自通知、外部链接、卡片或跨 Ability 跳转的参数。
  3. 生命周期回调里必须区分“初始化一次”“每次回前台都执行”“退出时释放”三类动作。
  4. 日志要带上业务标识,例如 routeId、taskId、target,方便真机调试时定位问题。

常见坑

使用 singleton 后只处理 onCreate,不处理 onNewWant,第二次打开同一 Ability 时页面仍显示旧数据。

验收标准

  • 能说清 实例管理 在 启动模式与实例管理 中承担的职责。
  • 代码能放进 DevEco Studio 工程中按小步验证,而不是只停留在伪代码。
  • 异常分支、生命周期切换和资源释放都有明确处理点。

7. 传递业务参数

图 7-7:传递业务参数

场景定位

本节把 传递业务参数 放到「通知、桌面图标、外部链接多入口同时打开同一个应用时,控制 Ability 实例数量和参数刷新」这个真实开发场景里理解。它不是孤立 API,而是围绕 启动模式决定系统如何复用 Ability 实例;选错模式会导致页面重复、参数丢失或任务栈混乱。 展开的一个工程动作。当前关注点是 实例管理,读者可以把它当成排查 AbilityKit 项目问题时的一条检查线。

实战代码

import UIAbility from '@ohos.app.ability.UIAbility';
import Want from '@ohos.app.ability.Want';

export default class DetailAbility extends UIAbility {
  private currentId = '';

  onCreate(want: Want): void {
    this.applyWant(want, 'create');
  }

  onNewWant(want: Want): void {
    this.applyWant(want, 'new-want');
  }

  private applyWant(want: Want, source: string): void {
    const id = String(want.parameters?.id ?? '');
    if (id && id !== this.currentId) {
      this.currentId = id;
      console.info(`[DetailAbility] ${source}, switch to id=${id}`);
    }
  }
}

代码解释

  1. 入口层只处理系统回调、上下文获取和启动协议,不把页面 UI 细节塞进 Ability。
  2. 业务参数要先校验再使用,尤其是来自通知、外部链接、卡片或跨 Ability 跳转的参数。
  3. 生命周期回调里必须区分“初始化一次”“每次回前台都执行”“退出时释放”三类动作。
  4. 日志要带上业务标识,例如 routeId、taskId、target,方便真机调试时定位问题。

常见坑

使用 singleton 后只处理 onCreate,不处理 onNewWant,第二次打开同一 Ability 时页面仍显示旧数据。

验收标准

  • 能说清 实例管理 在 启动模式与实例管理 中承担的职责。
  • 代码能放进 DevEco Studio 工程中按小步验证,而不是只停留在伪代码。
  • 异常分支、生命周期切换和资源释放都有明确处理点。

8. 读取 Context 能力

图 7-8:读取 Context 能力

场景定位

本节把 读取 Context 能力 放到「通知、桌面图标、外部链接多入口同时打开同一个应用时,控制 Ability 实例数量和参数刷新」这个真实开发场景里理解。它不是孤立 API,而是围绕 启动模式决定系统如何复用 Ability 实例;选错模式会导致页面重复、参数丢失或任务栈混乱。 展开的一个工程动作。当前关注点是 实例管理,读者可以把它当成排查 AbilityKit 项目问题时的一条检查线。

实战代码

import UIAbility from '@ohos.app.ability.UIAbility';
import Want from '@ohos.app.ability.Want';

export default class DetailAbility extends UIAbility {
  private currentId = '';

  onCreate(want: Want): void {
    this.applyWant(want, 'create');
  }

  onNewWant(want: Want): void {
    this.applyWant(want, 'new-want');
  }

  private applyWant(want: Want, source: string): void {
    const id = String(want.parameters?.id ?? '');
    if (id && id !== this.currentId) {
      this.currentId = id;
      console.info(`[DetailAbility] ${source}, switch to id=${id}`);
    }
  }
}

代码解释

  1. 入口层只处理系统回调、上下文获取和启动协议,不把页面 UI 细节塞进 Ability。
  2. 业务参数要先校验再使用,尤其是来自通知、外部链接、卡片或跨 Ability 跳转的参数。
  3. 生命周期回调里必须区分“初始化一次”“每次回前台都执行”“退出时释放”三类动作。
  4. 日志要带上业务标识,例如 routeId、taskId、target,方便真机调试时定位问题。

常见坑

使用 singleton 后只处理 onCreate,不处理 onNewWant,第二次打开同一 Ability 时页面仍显示旧数据。

验收标准

  • 能说清 实例管理 在 启动模式与实例管理 中承担的职责。
  • 代码能放进 DevEco Studio 工程中按小步验证,而不是只停留在伪代码。
  • 异常分支、生命周期切换和资源释放都有明确处理点。

9. 处理前后台切换

图 7-9:处理前后台切换

场景定位

本节把 处理前后台切换 放到「通知、桌面图标、外部链接多入口同时打开同一个应用时,控制 Ability 实例数量和参数刷新」这个真实开发场景里理解。它不是孤立 API,而是围绕 启动模式决定系统如何复用 Ability 实例;选错模式会导致页面重复、参数丢失或任务栈混乱。 展开的一个工程动作。当前关注点是 实例管理,读者可以把它当成排查 AbilityKit 项目问题时的一条检查线。

实战代码

import UIAbility from '@ohos.app.ability.UIAbility';
import Want from '@ohos.app.ability.Want';

export default class DetailAbility extends UIAbility {
  private currentId = '';

  onCreate(want: Want): void {
    this.applyWant(want, 'create');
  }

  onNewWant(want: Want): void {
    this.applyWant(want, 'new-want');
  }

  private applyWant(want: Want, source: string): void {
    const id = String(want.parameters?.id ?? '');
    if (id && id !== this.currentId) {
      this.currentId = id;
      console.info(`[DetailAbility] ${source}, switch to id=${id}`);
    }
  }
}

代码解释

  1. 入口层只处理系统回调、上下文获取和启动协议,不把页面 UI 细节塞进 Ability。
  2. 业务参数要先校验再使用,尤其是来自通知、外部链接、卡片或跨 Ability 跳转的参数。
  3. 生命周期回调里必须区分“初始化一次”“每次回前台都执行”“退出时释放”三类动作。
  4. 日志要带上业务标识,例如 routeId、taskId、target,方便真机调试时定位问题。

常见坑

使用 singleton 后只处理 onCreate,不处理 onNewWant,第二次打开同一 Ability 时页面仍显示旧数据。

验收标准

  • 能说清 实例管理 在 启动模式与实例管理 中承担的职责。
  • 代码能放进 DevEco Studio 工程中按小步验证,而不是只停留在伪代码。
  • 异常分支、生命周期切换和资源释放都有明确处理点。

10. 处理重复启动

图 7-10:处理重复启动

场景定位

本节把 处理重复启动 放到「通知、桌面图标、外部链接多入口同时打开同一个应用时,控制 Ability 实例数量和参数刷新」这个真实开发场景里理解。它不是孤立 API,而是围绕 启动模式决定系统如何复用 Ability 实例;选错模式会导致页面重复、参数丢失或任务栈混乱。 展开的一个工程动作。当前关注点是 实例管理,读者可以把它当成排查 AbilityKit 项目问题时的一条检查线。

实战代码

import UIAbility from '@ohos.app.ability.UIAbility';
import Want from '@ohos.app.ability.Want';

export default class DetailAbility extends UIAbility {
  private currentId = '';

  onCreate(want: Want): void {
    this.applyWant(want, 'create');
  }

  onNewWant(want: Want): void {
    this.applyWant(want, 'new-want');
  }

  private applyWant(want: Want, source: string): void {
    const id = String(want.parameters?.id ?? '');
    if (id && id !== this.currentId) {
      this.currentId = id;
      console.info(`[DetailAbility] ${source}, switch to id=${id}`);
    }
  }
}

代码解释

  1. 入口层只处理系统回调、上下文获取和启动协议,不把页面 UI 细节塞进 Ability。
  2. 业务参数要先校验再使用,尤其是来自通知、外部链接、卡片或跨 Ability 跳转的参数。
  3. 生命周期回调里必须区分“初始化一次”“每次回前台都执行”“退出时释放”三类动作。
  4. 日志要带上业务标识,例如 routeId、taskId、target,方便真机调试时定位问题。

常见坑

使用 singleton 后只处理 onCreate,不处理 onNewWant,第二次打开同一 Ability 时页面仍显示旧数据。

验收标准

  • 能说清 实例管理 在 启动模式与实例管理 中承担的职责。
  • 代码能放进 DevEco Studio 工程中按小步验证,而不是只停留在伪代码。
  • 异常分支、生命周期切换和资源释放都有明确处理点。

11. 处理异常兜底

图 7-11:处理异常兜底

场景定位

本节把 处理异常兜底 放到「通知、桌面图标、外部链接多入口同时打开同一个应用时,控制 Ability 实例数量和参数刷新」这个真实开发场景里理解。它不是孤立 API,而是围绕 启动模式决定系统如何复用 Ability 实例;选错模式会导致页面重复、参数丢失或任务栈混乱。 展开的一个工程动作。当前关注点是 实例管理,读者可以把它当成排查 AbilityKit 项目问题时的一条检查线。

实战代码

import UIAbility from '@ohos.app.ability.UIAbility';
import Want from '@ohos.app.ability.Want';

export default class DetailAbility extends UIAbility {
  private currentId = '';

  onCreate(want: Want): void {
    this.applyWant(want, 'create');
  }

  onNewWant(want: Want): void {
    this.applyWant(want, 'new-want');
  }

  private applyWant(want: Want, source: string): void {
    const id = String(want.parameters?.id ?? '');
    if (id && id !== this.currentId) {
      this.currentId = id;
      console.info(`[DetailAbility] ${source}, switch to id=${id}`);
    }
  }
}

代码解释

  1. 入口层只处理系统回调、上下文获取和启动协议,不把页面 UI 细节塞进 Ability。
  2. 业务参数要先校验再使用,尤其是来自通知、外部链接、卡片或跨 Ability 跳转的参数。
  3. 生命周期回调里必须区分“初始化一次”“每次回前台都执行”“退出时释放”三类动作。
  4. 日志要带上业务标识,例如 routeId、taskId、target,方便真机调试时定位问题。

常见坑

使用 singleton 后只处理 onCreate,不处理 onNewWant,第二次打开同一 Ability 时页面仍显示旧数据。

验收标准

  • 能说清 实例管理 在 启动模式与实例管理 中承担的职责。
  • 代码能放进 DevEco Studio 工程中按小步验证,而不是只停留在伪代码。
  • 异常分支、生命周期切换和资源释放都有明确处理点。

12. 释放页面资源

图 7-12:释放页面资源

场景定位

本节把 释放页面资源 放到「通知、桌面图标、外部链接多入口同时打开同一个应用时,控制 Ability 实例数量和参数刷新」这个真实开发场景里理解。它不是孤立 API,而是围绕 启动模式决定系统如何复用 Ability 实例;选错模式会导致页面重复、参数丢失或任务栈混乱。 展开的一个工程动作。当前关注点是 实例管理,读者可以把它当成排查 AbilityKit 项目问题时的一条检查线。

实战代码

import UIAbility from '@ohos.app.ability.UIAbility';
import Want from '@ohos.app.ability.Want';

export default class DetailAbility extends UIAbility {
  private currentId = '';

  onCreate(want: Want): void {
    this.applyWant(want, 'create');
  }

  onNewWant(want: Want): void {
    this.applyWant(want, 'new-want');
  }

  private applyWant(want: Want, source: string): void {
    const id = String(want.parameters?.id ?? '');
    if (id && id !== this.currentId) {
      this.currentId = id;
      console.info(`[DetailAbility] ${source}, switch to id=${id}`);
    }
  }
}

代码解释

  1. 入口层只处理系统回调、上下文获取和启动协议,不把页面 UI 细节塞进 Ability。
  2. 业务参数要先校验再使用,尤其是来自通知、外部链接、卡片或跨 Ability 跳转的参数。
  3. 生命周期回调里必须区分“初始化一次”“每次回前台都执行”“退出时释放”三类动作。
  4. 日志要带上业务标识,例如 routeId、taskId、target,方便真机调试时定位问题。

常见坑

使用 singleton 后只处理 onCreate,不处理 onNewWant,第二次打开同一 Ability 时页面仍显示旧数据。

验收标准

  • 能说清 实例管理 在 启动模式与实例管理 中承担的职责。
  • 代码能放进 DevEco Studio 工程中按小步验证,而不是只停留在伪代码。
  • 异常分支、生命周期切换和资源释放都有明确处理点。

13. 补充工程封装

图 7-13:补充工程封装

场景定位

本节把 补充工程封装 放到「通知、桌面图标、外部链接多入口同时打开同一个应用时,控制 Ability 实例数量和参数刷新」这个真实开发场景里理解。它不是孤立 API,而是围绕 启动模式决定系统如何复用 Ability 实例;选错模式会导致页面重复、参数丢失或任务栈混乱。 展开的一个工程动作。当前关注点是 实例管理,读者可以把它当成排查 AbilityKit 项目问题时的一条检查线。

实战代码

import UIAbility from '@ohos.app.ability.UIAbility';
import Want from '@ohos.app.ability.Want';

export default class DetailAbility extends UIAbility {
  private currentId = '';

  onCreate(want: Want): void {
    this.applyWant(want, 'create');
  }

  onNewWant(want: Want): void {
    this.applyWant(want, 'new-want');
  }

  private applyWant(want: Want, source: string): void {
    const id = String(want.parameters?.id ?? '');
    if (id && id !== this.currentId) {
      this.currentId = id;
      console.info(`[DetailAbility] ${source}, switch to id=${id}`);
    }
  }
}

代码解释

  1. 入口层只处理系统回调、上下文获取和启动协议,不把页面 UI 细节塞进 Ability。
  2. 业务参数要先校验再使用,尤其是来自通知、外部链接、卡片或跨 Ability 跳转的参数。
  3. 生命周期回调里必须区分“初始化一次”“每次回前台都执行”“退出时释放”三类动作。
  4. 日志要带上业务标识,例如 routeId、taskId、target,方便真机调试时定位问题。

常见坑

使用 singleton 后只处理 onCreate,不处理 onNewWant,第二次打开同一 Ability 时页面仍显示旧数据。

验收标准

  • 能说清 实例管理 在 启动模式与实例管理 中承担的职责。
  • 代码能放进 DevEco Studio 工程中按小步验证,而不是只停留在伪代码。
  • 异常分支、生命周期切换和资源释放都有明确处理点。

14. 设计验证清单

图 7-14:设计验证清单

场景定位

本节把 设计验证清单 放到「通知、桌面图标、外部链接多入口同时打开同一个应用时,控制 Ability 实例数量和参数刷新」这个真实开发场景里理解。它不是孤立 API,而是围绕 启动模式决定系统如何复用 Ability 实例;选错模式会导致页面重复、参数丢失或任务栈混乱。 展开的一个工程动作。当前关注点是 实例管理,读者可以把它当成排查 AbilityKit 项目问题时的一条检查线。

实战代码

import UIAbility from '@ohos.app.ability.UIAbility';
import Want from '@ohos.app.ability.Want';

export default class DetailAbility extends UIAbility {
  private currentId = '';

  onCreate(want: Want): void {
    this.applyWant(want, 'create');
  }

  onNewWant(want: Want): void {
    this.applyWant(want, 'new-want');
  }

  private applyWant(want: Want, source: string): void {
    const id = String(want.parameters?.id ?? '');
    if (id && id !== this.currentId) {
      this.currentId = id;
      console.info(`[DetailAbility] ${source}, switch to id=${id}`);
    }
  }
}

代码解释

  1. 入口层只处理系统回调、上下文获取和启动协议,不把页面 UI 细节塞进 Ability。
  2. 业务参数要先校验再使用,尤其是来自通知、外部链接、卡片或跨 Ability 跳转的参数。
  3. 生命周期回调里必须区分“初始化一次”“每次回前台都执行”“退出时释放”三类动作。
  4. 日志要带上业务标识,例如 routeId、taskId、target,方便真机调试时定位问题。

常见坑

使用 singleton 后只处理 onCreate,不处理 onNewWant,第二次打开同一 Ability 时页面仍显示旧数据。

验收标准

  • 能说清 实例管理 在 启动模式与实例管理 中承担的职责。
  • 代码能放进 DevEco Studio 工程中按小步验证,而不是只停留在伪代码。
  • 异常分支、生命周期切换和资源释放都有明确处理点。

15. 本节小结与练习

图 7-15:本节小结与练习

场景定位

本节把 本节小结与练习 放到「通知、桌面图标、外部链接多入口同时打开同一个应用时,控制 Ability 实例数量和参数刷新」这个真实开发场景里理解。它不是孤立 API,而是围绕 启动模式决定系统如何复用 Ability 实例;选错模式会导致页面重复、参数丢失或任务栈混乱。 展开的一个工程动作。当前关注点是 实例管理,读者可以把它当成排查 AbilityKit 项目问题时的一条检查线。

实战代码

import UIAbility from '@ohos.app.ability.UIAbility';
import Want from '@ohos.app.ability.Want';

export default class DetailAbility extends UIAbility {
  private currentId = '';

  onCreate(want: Want): void {
    this.applyWant(want, 'create');
  }

  onNewWant(want: Want): void {
    this.applyWant(want, 'new-want');
  }

  private applyWant(want: Want, source: string): void {
    const id = String(want.parameters?.id ?? '');
    if (id && id !== this.currentId) {
      this.currentId = id;
      console.info(`[DetailAbility] ${source}, switch to id=${id}`);
    }
  }
}

代码解释

  1. 入口层只处理系统回调、上下文获取和启动协议,不把页面 UI 细节塞进 Ability。
  2. 业务参数要先校验再使用,尤其是来自通知、外部链接、卡片或跨 Ability 跳转的参数。
  3. 生命周期回调里必须区分“初始化一次”“每次回前台都执行”“退出时释放”三类动作。
  4. 日志要带上业务标识,例如 routeId、taskId、target,方便真机调试时定位问题。

常见坑

使用 singleton 后只处理 onCreate,不处理 onNewWant,第二次打开同一 Ability 时页面仍显示旧数据。

验收标准

  • 能说清 实例管理 在 启动模式与实例管理 中承担的职责。
  • 代码能放进 DevEco Studio 工程中按小步验证,而不是只停留在伪代码。
  • 异常分支、生命周期切换和资源释放都有明确处理点。

参考资料

  • 华为 HarmonyOS 官方文档:AbilityKit / UIAbility / Stage 模型相关指南。
  • DevEco Studio 真机调试日志和 ArkTS 工程结构。
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐