UIAbility 生命周期实战:onCreate 到 onDestroy 的完整链路

主题关键词:UIAbility、onCreate、onWindowStageCreate、onForeground、onBackground、onDestroy。

封面

文章导读

  • 适合读者:已经会创建 HarmonyOS 工程,但对 AbilityKit 工程边界、生命周期和系统能力衔接不够清晰的开发者。
  • 本篇场景:一个带首页、详情页、定位刷新和后台恢复的 HarmonyOS 应用。
  • 本篇结论:生命周期回调不是用来堆业务代码的,而是用来决定初始化、页面加载、前后台恢复和资源释放的边界。
  • 阅读方式:先看每节配图,再复制关键代码,最后用验收清单检查自己的项目。

目录

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

1. 明确本节目标

图 2-1:明确本节目标

场景定位

本节把 明确本节目标 放到「一个带首页、详情页、定位刷新和后台恢复的 HarmonyOS 应用」这个真实开发场景里理解。它不是孤立 API,而是围绕 生命周期回调不是用来堆业务代码的,而是用来决定初始化、页面加载、前后台恢复和资源释放的边界。 展开的一个工程动作。当前关注点是 UIAbility,读者可以把它当成排查 AbilityKit 项目问题时的一条检查线。

实战代码

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

export default class EntryAbility extends UIAbility {
  private lastWant?: Want;
  private activeTimer: number = -1;

  onCreate(want: Want): void {
    this.lastWant = want;
    console.info(`[Ability] onCreate: ${JSON.stringify(want.parameters ?? {})}`);
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        console.error(`[Ability] loadContent failed: ${err.code}, ${err.message}`);
        return;
      }
      console.info('[Ability] Index page loaded');
    });
  }

  onForeground(): void {
    this.activeTimer = setInterval(() => console.info('refresh foreground data'), 30_000);
  }

  onBackground(): void {
    if (this.activeTimer >= 0) {
      clearInterval(this.activeTimer);
      this.activeTimer = -1;
    }
  }

  onDestroy(): void {
    console.info('[Ability] release global ability resources');
  }
}

代码解释

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

常见坑

把网络请求、定位监听、长定时器全部写在 ArkUI 页面里,页面看似能跑,但前后台切换后很容易重复监听或内存泄漏。

验收标准

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

2. 理解官方概念

图 2-2:理解官方概念

场景定位

本节把 理解官方概念 放到「一个带首页、详情页、定位刷新和后台恢复的 HarmonyOS 应用」这个真实开发场景里理解。它不是孤立 API,而是围绕 生命周期回调不是用来堆业务代码的,而是用来决定初始化、页面加载、前后台恢复和资源释放的边界。 展开的一个工程动作。当前关注点是 onCreate,读者可以把它当成排查 AbilityKit 项目问题时的一条检查线。

实战代码

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

export default class EntryAbility extends UIAbility {
  private lastWant?: Want;
  private activeTimer: number = -1;

  onCreate(want: Want): void {
    this.lastWant = want;
    console.info(`[Ability] onCreate: ${JSON.stringify(want.parameters ?? {})}`);
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        console.error(`[Ability] loadContent failed: ${err.code}, ${err.message}`);
        return;
      }
      console.info('[Ability] Index page loaded');
    });
  }

  onForeground(): void {
    this.activeTimer = setInterval(() => console.info('refresh foreground data'), 30_000);
  }

  onBackground(): void {
    if (this.activeTimer >= 0) {
      clearInterval(this.activeTimer);
      this.activeTimer = -1;
    }
  }

  onDestroy(): void {
    console.info('[Ability] release global ability resources');
  }
}

代码解释

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

常见坑

把网络请求、定位监听、长定时器全部写在 ArkUI 页面里,页面看似能跑,但前后台切换后很容易重复监听或内存泄漏。

验收标准

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

3. 建立最小工程结构

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

场景定位

本节把 建立最小工程结构 放到「一个带首页、详情页、定位刷新和后台恢复的 HarmonyOS 应用」这个真实开发场景里理解。它不是孤立 API,而是围绕 生命周期回调不是用来堆业务代码的,而是用来决定初始化、页面加载、前后台恢复和资源释放的边界。 展开的一个工程动作。当前关注点是 onWindowStageCreate,读者可以把它当成排查 AbilityKit 项目问题时的一条检查线。

实战代码

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

export default class EntryAbility extends UIAbility {
  private lastWant?: Want;
  private activeTimer: number = -1;

  onCreate(want: Want): void {
    this.lastWant = want;
    console.info(`[Ability] onCreate: ${JSON.stringify(want.parameters ?? {})}`);
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        console.error(`[Ability] loadContent failed: ${err.code}, ${err.message}`);
        return;
      }
      console.info('[Ability] Index page loaded');
    });
  }

  onForeground(): void {
    this.activeTimer = setInterval(() => console.info('refresh foreground data'), 30_000);
  }

  onBackground(): void {
    if (this.activeTimer >= 0) {
      clearInterval(this.activeTimer);
      this.activeTimer = -1;
    }
  }

  onDestroy(): void {
    console.info('[Ability] release global ability resources');
  }
}

代码解释

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

常见坑

把网络请求、定位监听、长定时器全部写在 ArkUI 页面里,页面看似能跑,但前后台切换后很容易重复监听或内存泄漏。

验收标准

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

4. 声明 Ability 配置

图 2-4:声明 Ability 配置

场景定位

本节把 声明 Ability 配置 放到「一个带首页、详情页、定位刷新和后台恢复的 HarmonyOS 应用」这个真实开发场景里理解。它不是孤立 API,而是围绕 生命周期回调不是用来堆业务代码的,而是用来决定初始化、页面加载、前后台恢复和资源释放的边界。 展开的一个工程动作。当前关注点是 onForeground,读者可以把它当成排查 AbilityKit 项目问题时的一条检查线。

实战代码

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

export default class EntryAbility extends UIAbility {
  private lastWant?: Want;
  private activeTimer: number = -1;

  onCreate(want: Want): void {
    this.lastWant = want;
    console.info(`[Ability] onCreate: ${JSON.stringify(want.parameters ?? {})}`);
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        console.error(`[Ability] loadContent failed: ${err.code}, ${err.message}`);
        return;
      }
      console.info('[Ability] Index page loaded');
    });
  }

  onForeground(): void {
    this.activeTimer = setInterval(() => console.info('refresh foreground data'), 30_000);
  }

  onBackground(): void {
    if (this.activeTimer >= 0) {
      clearInterval(this.activeTimer);
      this.activeTimer = -1;
    }
  }

  onDestroy(): void {
    console.info('[Ability] release global ability resources');
  }
}

代码解释

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

常见坑

把网络请求、定位监听、长定时器全部写在 ArkUI 页面里,页面看似能跑,但前后台切换后很容易重复监听或内存泄漏。

验收标准

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

5. 实现生命周期入口

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

场景定位

本节把 实现生命周期入口 放到「一个带首页、详情页、定位刷新和后台恢复的 HarmonyOS 应用」这个真实开发场景里理解。它不是孤立 API,而是围绕 生命周期回调不是用来堆业务代码的,而是用来决定初始化、页面加载、前后台恢复和资源释放的边界。 展开的一个工程动作。当前关注点是 onBackground,读者可以把它当成排查 AbilityKit 项目问题时的一条检查线。

实战代码

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

export default class EntryAbility extends UIAbility {
  private lastWant?: Want;
  private activeTimer: number = -1;

  onCreate(want: Want): void {
    this.lastWant = want;
    console.info(`[Ability] onCreate: ${JSON.stringify(want.parameters ?? {})}`);
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        console.error(`[Ability] loadContent failed: ${err.code}, ${err.message}`);
        return;
      }
      console.info('[Ability] Index page loaded');
    });
  }

  onForeground(): void {
    this.activeTimer = setInterval(() => console.info('refresh foreground data'), 30_000);
  }

  onBackground(): void {
    if (this.activeTimer >= 0) {
      clearInterval(this.activeTimer);
      this.activeTimer = -1;
    }
  }

  onDestroy(): void {
    console.info('[Ability] release global ability resources');
  }
}

代码解释

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

常见坑

把网络请求、定位监听、长定时器全部写在 ArkUI 页面里,页面看似能跑,但前后台切换后很容易重复监听或内存泄漏。

验收标准

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

6. 加载 ArkUI 页面

图 2-6:加载 ArkUI 页面

场景定位

本节把 加载 ArkUI 页面 放到「一个带首页、详情页、定位刷新和后台恢复的 HarmonyOS 应用」这个真实开发场景里理解。它不是孤立 API,而是围绕 生命周期回调不是用来堆业务代码的,而是用来决定初始化、页面加载、前后台恢复和资源释放的边界。 展开的一个工程动作。当前关注点是 onDestroy,读者可以把它当成排查 AbilityKit 项目问题时的一条检查线。

实战代码

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

export default class EntryAbility extends UIAbility {
  private lastWant?: Want;
  private activeTimer: number = -1;

  onCreate(want: Want): void {
    this.lastWant = want;
    console.info(`[Ability] onCreate: ${JSON.stringify(want.parameters ?? {})}`);
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        console.error(`[Ability] loadContent failed: ${err.code}, ${err.message}`);
        return;
      }
      console.info('[Ability] Index page loaded');
    });
  }

  onForeground(): void {
    this.activeTimer = setInterval(() => console.info('refresh foreground data'), 30_000);
  }

  onBackground(): void {
    if (this.activeTimer >= 0) {
      clearInterval(this.activeTimer);
      this.activeTimer = -1;
    }
  }

  onDestroy(): void {
    console.info('[Ability] release global ability resources');
  }
}

代码解释

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

常见坑

把网络请求、定位监听、长定时器全部写在 ArkUI 页面里,页面看似能跑,但前后台切换后很容易重复监听或内存泄漏。

验收标准

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

7. 传递业务参数

图 2-7:传递业务参数

场景定位

本节把 传递业务参数 放到「一个带首页、详情页、定位刷新和后台恢复的 HarmonyOS 应用」这个真实开发场景里理解。它不是孤立 API,而是围绕 生命周期回调不是用来堆业务代码的,而是用来决定初始化、页面加载、前后台恢复和资源释放的边界。 展开的一个工程动作。当前关注点是 onDestroy,读者可以把它当成排查 AbilityKit 项目问题时的一条检查线。

实战代码

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

export default class EntryAbility extends UIAbility {
  private lastWant?: Want;
  private activeTimer: number = -1;

  onCreate(want: Want): void {
    this.lastWant = want;
    console.info(`[Ability] onCreate: ${JSON.stringify(want.parameters ?? {})}`);
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        console.error(`[Ability] loadContent failed: ${err.code}, ${err.message}`);
        return;
      }
      console.info('[Ability] Index page loaded');
    });
  }

  onForeground(): void {
    this.activeTimer = setInterval(() => console.info('refresh foreground data'), 30_000);
  }

  onBackground(): void {
    if (this.activeTimer >= 0) {
      clearInterval(this.activeTimer);
      this.activeTimer = -1;
    }
  }

  onDestroy(): void {
    console.info('[Ability] release global ability resources');
  }
}

代码解释

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

常见坑

把网络请求、定位监听、长定时器全部写在 ArkUI 页面里,页面看似能跑,但前后台切换后很容易重复监听或内存泄漏。

验收标准

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

8. 读取 Context 能力

图 2-8:读取 Context 能力

场景定位

本节把 读取 Context 能力 放到「一个带首页、详情页、定位刷新和后台恢复的 HarmonyOS 应用」这个真实开发场景里理解。它不是孤立 API,而是围绕 生命周期回调不是用来堆业务代码的,而是用来决定初始化、页面加载、前后台恢复和资源释放的边界。 展开的一个工程动作。当前关注点是 onDestroy,读者可以把它当成排查 AbilityKit 项目问题时的一条检查线。

实战代码

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

export default class EntryAbility extends UIAbility {
  private lastWant?: Want;
  private activeTimer: number = -1;

  onCreate(want: Want): void {
    this.lastWant = want;
    console.info(`[Ability] onCreate: ${JSON.stringify(want.parameters ?? {})}`);
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        console.error(`[Ability] loadContent failed: ${err.code}, ${err.message}`);
        return;
      }
      console.info('[Ability] Index page loaded');
    });
  }

  onForeground(): void {
    this.activeTimer = setInterval(() => console.info('refresh foreground data'), 30_000);
  }

  onBackground(): void {
    if (this.activeTimer >= 0) {
      clearInterval(this.activeTimer);
      this.activeTimer = -1;
    }
  }

  onDestroy(): void {
    console.info('[Ability] release global ability resources');
  }
}

代码解释

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

常见坑

把网络请求、定位监听、长定时器全部写在 ArkUI 页面里,页面看似能跑,但前后台切换后很容易重复监听或内存泄漏。

验收标准

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

9. 处理前后台切换

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

场景定位

本节把 处理前后台切换 放到「一个带首页、详情页、定位刷新和后台恢复的 HarmonyOS 应用」这个真实开发场景里理解。它不是孤立 API,而是围绕 生命周期回调不是用来堆业务代码的,而是用来决定初始化、页面加载、前后台恢复和资源释放的边界。 展开的一个工程动作。当前关注点是 onDestroy,读者可以把它当成排查 AbilityKit 项目问题时的一条检查线。

实战代码

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

export default class EntryAbility extends UIAbility {
  private lastWant?: Want;
  private activeTimer: number = -1;

  onCreate(want: Want): void {
    this.lastWant = want;
    console.info(`[Ability] onCreate: ${JSON.stringify(want.parameters ?? {})}`);
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        console.error(`[Ability] loadContent failed: ${err.code}, ${err.message}`);
        return;
      }
      console.info('[Ability] Index page loaded');
    });
  }

  onForeground(): void {
    this.activeTimer = setInterval(() => console.info('refresh foreground data'), 30_000);
  }

  onBackground(): void {
    if (this.activeTimer >= 0) {
      clearInterval(this.activeTimer);
      this.activeTimer = -1;
    }
  }

  onDestroy(): void {
    console.info('[Ability] release global ability resources');
  }
}

代码解释

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

常见坑

把网络请求、定位监听、长定时器全部写在 ArkUI 页面里,页面看似能跑,但前后台切换后很容易重复监听或内存泄漏。

验收标准

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

10. 处理重复启动

图 2-10:处理重复启动

场景定位

本节把 处理重复启动 放到「一个带首页、详情页、定位刷新和后台恢复的 HarmonyOS 应用」这个真实开发场景里理解。它不是孤立 API,而是围绕 生命周期回调不是用来堆业务代码的,而是用来决定初始化、页面加载、前后台恢复和资源释放的边界。 展开的一个工程动作。当前关注点是 onDestroy,读者可以把它当成排查 AbilityKit 项目问题时的一条检查线。

实战代码

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

export default class EntryAbility extends UIAbility {
  private lastWant?: Want;
  private activeTimer: number = -1;

  onCreate(want: Want): void {
    this.lastWant = want;
    console.info(`[Ability] onCreate: ${JSON.stringify(want.parameters ?? {})}`);
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        console.error(`[Ability] loadContent failed: ${err.code}, ${err.message}`);
        return;
      }
      console.info('[Ability] Index page loaded');
    });
  }

  onForeground(): void {
    this.activeTimer = setInterval(() => console.info('refresh foreground data'), 30_000);
  }

  onBackground(): void {
    if (this.activeTimer >= 0) {
      clearInterval(this.activeTimer);
      this.activeTimer = -1;
    }
  }

  onDestroy(): void {
    console.info('[Ability] release global ability resources');
  }
}

代码解释

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

常见坑

把网络请求、定位监听、长定时器全部写在 ArkUI 页面里,页面看似能跑,但前后台切换后很容易重复监听或内存泄漏。

验收标准

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

11. 处理异常兜底

图 2-11:处理异常兜底

场景定位

本节把 处理异常兜底 放到「一个带首页、详情页、定位刷新和后台恢复的 HarmonyOS 应用」这个真实开发场景里理解。它不是孤立 API,而是围绕 生命周期回调不是用来堆业务代码的,而是用来决定初始化、页面加载、前后台恢复和资源释放的边界。 展开的一个工程动作。当前关注点是 onDestroy,读者可以把它当成排查 AbilityKit 项目问题时的一条检查线。

实战代码

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

export default class EntryAbility extends UIAbility {
  private lastWant?: Want;
  private activeTimer: number = -1;

  onCreate(want: Want): void {
    this.lastWant = want;
    console.info(`[Ability] onCreate: ${JSON.stringify(want.parameters ?? {})}`);
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        console.error(`[Ability] loadContent failed: ${err.code}, ${err.message}`);
        return;
      }
      console.info('[Ability] Index page loaded');
    });
  }

  onForeground(): void {
    this.activeTimer = setInterval(() => console.info('refresh foreground data'), 30_000);
  }

  onBackground(): void {
    if (this.activeTimer >= 0) {
      clearInterval(this.activeTimer);
      this.activeTimer = -1;
    }
  }

  onDestroy(): void {
    console.info('[Ability] release global ability resources');
  }
}

代码解释

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

常见坑

把网络请求、定位监听、长定时器全部写在 ArkUI 页面里,页面看似能跑,但前后台切换后很容易重复监听或内存泄漏。

验收标准

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

12. 释放页面资源

图 2-12:释放页面资源

场景定位

本节把 释放页面资源 放到「一个带首页、详情页、定位刷新和后台恢复的 HarmonyOS 应用」这个真实开发场景里理解。它不是孤立 API,而是围绕 生命周期回调不是用来堆业务代码的,而是用来决定初始化、页面加载、前后台恢复和资源释放的边界。 展开的一个工程动作。当前关注点是 onDestroy,读者可以把它当成排查 AbilityKit 项目问题时的一条检查线。

实战代码

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

export default class EntryAbility extends UIAbility {
  private lastWant?: Want;
  private activeTimer: number = -1;

  onCreate(want: Want): void {
    this.lastWant = want;
    console.info(`[Ability] onCreate: ${JSON.stringify(want.parameters ?? {})}`);
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        console.error(`[Ability] loadContent failed: ${err.code}, ${err.message}`);
        return;
      }
      console.info('[Ability] Index page loaded');
    });
  }

  onForeground(): void {
    this.activeTimer = setInterval(() => console.info('refresh foreground data'), 30_000);
  }

  onBackground(): void {
    if (this.activeTimer >= 0) {
      clearInterval(this.activeTimer);
      this.activeTimer = -1;
    }
  }

  onDestroy(): void {
    console.info('[Ability] release global ability resources');
  }
}

代码解释

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

常见坑

把网络请求、定位监听、长定时器全部写在 ArkUI 页面里,页面看似能跑,但前后台切换后很容易重复监听或内存泄漏。

验收标准

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

13. 补充工程封装

图 2-13:补充工程封装

场景定位

本节把 补充工程封装 放到「一个带首页、详情页、定位刷新和后台恢复的 HarmonyOS 应用」这个真实开发场景里理解。它不是孤立 API,而是围绕 生命周期回调不是用来堆业务代码的,而是用来决定初始化、页面加载、前后台恢复和资源释放的边界。 展开的一个工程动作。当前关注点是 onDestroy,读者可以把它当成排查 AbilityKit 项目问题时的一条检查线。

实战代码

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

export default class EntryAbility extends UIAbility {
  private lastWant?: Want;
  private activeTimer: number = -1;

  onCreate(want: Want): void {
    this.lastWant = want;
    console.info(`[Ability] onCreate: ${JSON.stringify(want.parameters ?? {})}`);
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        console.error(`[Ability] loadContent failed: ${err.code}, ${err.message}`);
        return;
      }
      console.info('[Ability] Index page loaded');
    });
  }

  onForeground(): void {
    this.activeTimer = setInterval(() => console.info('refresh foreground data'), 30_000);
  }

  onBackground(): void {
    if (this.activeTimer >= 0) {
      clearInterval(this.activeTimer);
      this.activeTimer = -1;
    }
  }

  onDestroy(): void {
    console.info('[Ability] release global ability resources');
  }
}

代码解释

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

常见坑

把网络请求、定位监听、长定时器全部写在 ArkUI 页面里,页面看似能跑,但前后台切换后很容易重复监听或内存泄漏。

验收标准

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

14. 设计验证清单

图 2-14:设计验证清单

场景定位

本节把 设计验证清单 放到「一个带首页、详情页、定位刷新和后台恢复的 HarmonyOS 应用」这个真实开发场景里理解。它不是孤立 API,而是围绕 生命周期回调不是用来堆业务代码的,而是用来决定初始化、页面加载、前后台恢复和资源释放的边界。 展开的一个工程动作。当前关注点是 onDestroy,读者可以把它当成排查 AbilityKit 项目问题时的一条检查线。

实战代码

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

export default class EntryAbility extends UIAbility {
  private lastWant?: Want;
  private activeTimer: number = -1;

  onCreate(want: Want): void {
    this.lastWant = want;
    console.info(`[Ability] onCreate: ${JSON.stringify(want.parameters ?? {})}`);
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        console.error(`[Ability] loadContent failed: ${err.code}, ${err.message}`);
        return;
      }
      console.info('[Ability] Index page loaded');
    });
  }

  onForeground(): void {
    this.activeTimer = setInterval(() => console.info('refresh foreground data'), 30_000);
  }

  onBackground(): void {
    if (this.activeTimer >= 0) {
      clearInterval(this.activeTimer);
      this.activeTimer = -1;
    }
  }

  onDestroy(): void {
    console.info('[Ability] release global ability resources');
  }
}

代码解释

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

常见坑

把网络请求、定位监听、长定时器全部写在 ArkUI 页面里,页面看似能跑,但前后台切换后很容易重复监听或内存泄漏。

验收标准

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

15. 本节小结与练习

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

场景定位

本节把 本节小结与练习 放到「一个带首页、详情页、定位刷新和后台恢复的 HarmonyOS 应用」这个真实开发场景里理解。它不是孤立 API,而是围绕 生命周期回调不是用来堆业务代码的,而是用来决定初始化、页面加载、前后台恢复和资源释放的边界。 展开的一个工程动作。当前关注点是 onDestroy,读者可以把它当成排查 AbilityKit 项目问题时的一条检查线。

实战代码

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

export default class EntryAbility extends UIAbility {
  private lastWant?: Want;
  private activeTimer: number = -1;

  onCreate(want: Want): void {
    this.lastWant = want;
    console.info(`[Ability] onCreate: ${JSON.stringify(want.parameters ?? {})}`);
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        console.error(`[Ability] loadContent failed: ${err.code}, ${err.message}`);
        return;
      }
      console.info('[Ability] Index page loaded');
    });
  }

  onForeground(): void {
    this.activeTimer = setInterval(() => console.info('refresh foreground data'), 30_000);
  }

  onBackground(): void {
    if (this.activeTimer >= 0) {
      clearInterval(this.activeTimer);
      this.activeTimer = -1;
    }
  }

  onDestroy(): void {
    console.info('[Ability] release global ability resources');
  }
}

代码解释

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

常见坑

把网络请求、定位监听、长定时器全部写在 ArkUI 页面里,页面看似能跑,但前后台切换后很容易重复监听或内存泄漏。

验收标准

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

参考资料

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

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

更多推荐