页面预览

阅读时长:约 18 分钟 | 难度:★★★★☆ | 篇章:第 1 篇 · 项目架构与设计哲学
对应源码:entry/src/main/ets/entryability/EntryAbility.etsentrybackupability/EntryBackupAbility.ets

Ability设计决策图

前言

在 HarmonyOS Stage 模型下,Ability 是应用的功能载体。一个应用可以包含一个或多个 UIAbility,每个 UIAbility 实例对应一个任务。玄象项目作为单入口应用,采用了"一个 EntryAbility + 一个 EntryBackupAbility 扩展能力"的最小化设计。本篇将深入剖析玄象项目的 Ability 设计决策:何时该用单 Ability、何时该拆分多 Ability、备份扩展能力如何接入。

提示:Ability 数量直接决定了应用的任务管理行为、跨设备迁移能力、内存占用水平。错误的 Ability 拆分策略会导致用户体验割裂。

一、Ability 分类与玄象项目选择

1.1 HarmonyOS Ability 分类

HarmonyOS 提供两类 Ability:

类型 职责 是否有 UI 典型场景
UIAbility 包含 UI 界面的能力 主入口、设置页、独立功能区
ExtensionAbility 无 UI 的扩展能力 备份、卡片服务、输入法

1.2 玄象项目的 Ability 配置

玄象项目在 module.json5 中声明了 2 个 Ability:

{
  "abilities": [
    {
      "name": "EntryAbility",
      "srcEntry": "./ets/entryability/EntryAbility.ets",
      "description": "$string:EntryAbility_desc",
      "icon": "$media:layered_image",
      "label": "$string:EntryAbility_label",
      "startWindowIcon": "$media:startIcon",
      "startWindowBackground": "$color:start_window_background",
      "exported": true,
      "skills": [
        {
          "entities": ["entity.system.home"],
          "actions": ["ohos.want.action.home"]
        }
      ]
    }
  ],
  "extensionAbilities": [
    {
      "name": "EntryBackupAbility",
      "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets",
      "type": "backup",
      "exported": false,
      "metadata": [
        {
          "name": "ohos.extension.backup",
          "resource": "$profile:backup_config"
        }
      ]
    }
  ]
}

1.3 选择单 UIAbility 的考量

玄象项目选择 单一 EntryAbility 的核心考量:

  1. 单入口应用:玄象所有功能均从首页九宫格进入,无独立入口。
  2. 统一任务栈:所有页面在同一任务中,返回行为一致。
  3. 简化生命周期:单一 Ability 减少生命周期回调的复杂度。
  4. 降低内存占用:多 Ability 会创建多任务实例,增加内存压力。

提示:如果玄象未来推出"独立罗盘"功能,希望用户从桌面直接进入罗盘界面(而非通过首页),此时应该新增一个 LuopanAbility

二、EntryAbility 深度解析

2.1 完整源码

import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';

const DOMAIN = 0x0000;

export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    try {
      this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
    } catch (err) {
      hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err));
    }
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');
  }

  onDestroy(): void {
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy');
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
        return;
      }
      hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');
    });
  }

  onWindowStageDestroy(): void {
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
  }

  onForeground(): void {
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground');
  }

  onBackground(): void {
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground');
  }
}

2.2 import 语句解析

import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';

玄象项目引入了三个 Kit:

Kit 用途 玄象使用
@kit.AbilityKit Ability 能力 UIAbility 基类、Want 参数
@kit.PerformanceAnalysisKit 性能分析 hilog 日志
@kit.ArkUI ArkUI 框架 window.WindowStage

2.3 DOMAIN 日志域

const DOMAIN = 0x0000;

玄象项目使用 0x0000 作为日志域。hilog 是 HarmonyOS 的官方日志系统,通过 DOMAINtag 双重标识日志来源。

提示:生产环境建议为不同模块分配不同的 DOMAIN(如 0x0001 为入口、0x0002 为星宿模块),便于日志过滤与排查。

2.4 onCreate 初始化

onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  try {
    this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
  } catch (err) {
    hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err));
  }
  hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');
}

玄象项目在 onCreate 中做了两件事:

  1. 设置颜色模式:调用 setColorMode(COLOR_MODE_NOT_SET),表示跟随系统颜色模式。
  2. 输出日志:记录 Ability 创建事件。

try-catch 包裹的意义setColorMode 在某些低版本系统上可能抛出异常,玄象项目通过 try-catch 防止应用崩溃。这是 HarmonyOS 应用兼容性处理的典型范式。

2.5 onWindowStageCreate 加载首页

onWindowStageCreate(windowStage: window.WindowStage): void {
  hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
  windowStage.loadContent('pages/Index', (err) => {
    if (err.code) {
      hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
      return;
    }
    hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');
  });
}

onWindowStageCreate 是 UIAbility 最关键的回调,玄象项目在此加载首页 pages/Index

loadContent 回调规范

  1. 检查 err.code:非 0 表示加载失败。
  2. 错误日志:用 JSON.stringify(err) 输出完整错误信息。
  3. 成功日志:记录加载成功事件。

提示:玄象项目的 pages/Index 内部用 Navigation 包裹了 SplashPage,启动页加载完后 replaceUrlHomePage。这种"启动页 → 首页"的 3 秒过渡是玄象项目精心设计的用户体验。

三、EntryBackupAbility 备份扩展能力

3.1 完整源码

import { hilog } from '@kit.PerformanceAnalysisKit';
import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit';

const DOMAIN = 0x0000;

export default class EntryBackupAbility extends BackupExtensionAbility {
  async onBackup() {
    hilog.info(0x0000, 'testTag', 'onBackup ok');
    await Promise.resolve();
  }

  async onRestore(bundleVersion: BundleVersion) {
    hilog.info(0x0000, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion));
    await Promise.resolve();
  }
}

3.2 BackupExtensionAbility 的作用

BackupExtensionAbility 是 HarmonyOS 提供的 云端备份扩展能力,允许应用在系统备份/恢复时介入处理:

  • onBackup:系统备份时回调,应用可在此保存关键状态。
  • onRestore:系统恢复时回调,应用可在此恢复数据并处理版本迁移。

3.3 备份配置文件

玄象项目在 module.json5 中引用了 $profile:backup_config,该配置文件位于 resources/base/profile/backup_config.json

{
  "allowToBackupRestore": true
}

配置项说明

字段 类型 说明
allowToBackupRestore boolean 是否允许备份恢复

提示:玄象项目当前 onBackup / onRestore 仅输出日志,未做实质性数据处理。未来可在 onBackup 中保存用户偏好(如主题色、字体大小),在 onRestore 中恢复这些偏好。

四、UIAbility 生命周期详解

4.1 生命周期总览

玄象项目 EntryAbility 实现了全部 6 个生命周期回调:

应用启动
   ↓
onCreate         ← Ability 创建,初始化配置
   ↓
onWindowStageCreate  ← 窗口创建,加载首页
   ↓
[用户使用应用]
   ↓
onForeground     ← 切到前台
   ↓
onBackground     ← 切到后台
   ↓
[用户切回应用]
   ↓
onWindowStageDestroy  ← 窗口销毁
   ↓
onDestroy        ← Ability 销毁

4.2 生命周期回调清单

回调 触发时机 玄象用途 典型操作
onCreate Ability 创建 设置颜色模式 全局配置初始化
onDestroy Ability 销毁 输出日志 资源释放
onWindowStageCreate 窗口创建 加载 pages/Index loadContent
onWindowStageDestroy 窗口销毁 输出日志 UI 资源释放
onForeground 切到前台 输出日志 恢复计时器、刷新数据
onBackground 切到后台 输出日志 暂停计时器、保存状态

4.3 玄象项目生命周期最佳实践

玄象项目在生命周期回调中遵循以下原则:

  1. onCreate 只做轻量初始化:避免阻塞应用启动。
  2. onWindowStageCreate 加载首页:使用 loadContent 异步加载。
  3. onForeground / onBackground 处理状态切换:恢复/暂停计时器。
  4. onDestroy 释放资源:清理定时器、关闭文件句柄。

五、Want 与启动参数

5.1 Want 的概念

Want 是 HarmonyOS 中描述"想要做什么"的对象,用于 Ability 间通信。玄象项目的 EntryAbility 通过 skills 字段声明可接收的 Want:

"skills": [
  {
    "entities": ["entity.system.home"],
    "actions": ["ohos.want.action.home"]
  }
]

5.2 Want 的核心字段

字段 类型 说明
bundleName string 目标应用包名
abilityName string 目标 Ability 名称
uri string 数据 URI
type string 数据 MIME 类型
action string 操作类型
entities string[] 实体类别
parameters Record 自定义参数

5.3 onCreate 中接收 Want

玄象项目在 onCreate 中接收 want 参数:

onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  // want.parameters 可获取外部传入的参数
  // 玄象项目当前未使用 want 参数
  // ...
}

提示:如果玄象未来支持"通过通知跳转到特定星宿详情页",可在通知的 Want 中携带 mansionId 参数,EntryAbility 在 onCreate 中读取并传给首页。

六、context 上下文的能力访问

6.1 context 的核心作用

this.context 是 UIAbility 的上下文对象,提供应用级能力访问:

this.context.getApplicationContext().setColorMode(...);

6.2 context 提供的关键 API

API 用途
getApplicationContext() 获取应用级上下文
getFilesDir() 获取应用文件目录
getCacheDir() 获取缓存目录
getExternalFilesDir() 获取外部存储目录
requestPermissionsFromUser() 动态申请权限
terminateSelf() 销毁自身

6.3 玄象项目对 context 的使用

玄象项目当前仅在 onCreate 中通过 context.getApplicationContext() 设置颜色模式。未来在 GPS 风水、AI 拍照风水等功能中,将更频繁地使用 context.requestPermissionsFromUser() 动态申请权限。

七、单 Ability vs 多 Ability 决策矩阵

7.1 何时选择单 UIAbility

玄象项目选择单 UIAbility 的场景:

  1. 统一入口应用:所有功能从首页进入。
  2. 强关联页面:页面间跳转频繁,需要统一任务栈。
  3. 共享状态:页面间共享全局状态(如登录态)。
  4. 资源节约:减少多 Ability 创建的开销。

7.2 何时选择多 UIAbility

适合拆分多 UIAbility 的场景:

场景 拆分理由
独立功能入口 用户可直接从桌面进入特定功能
独立任务管理 不同功能需要独立任务栈
跨设备迁移 不同功能需要独立迁移
权限隔离 不同功能需要不同权限集

7.3 玄象项目的未来 Ability 拆分设想

玄象项目若未来推出以下功能,应考虑拆分多 UIAbility:

  1. LuopanAbility:独立罗盘功能,用户从桌面直接进入罗盘。
  2. WidgetAbility:桌面卡片服务,提供每日宜忌卡片。
  3. AssistantAbility:AI 助手独立任务,便于多窗口协同。

提示:Ability 拆分是架构演进的核心议题。玄象项目当前阶段保持单 UIAbility 是合理决策,未来扩展时再按需拆分。

八、EntryAbility 与 EntryBackupAbility 的协同

8.1 协同关系图

[应用启动]
   ↓
EntryAbility.onCreate()
   ↓
EntryAbility.onWindowStageCreate()
   ↓
loadContent('pages/Index')
   ↓
[SplashPage 3 秒后] → [HomePage 渲染]
   ↓
[用户使用应用]
   ↓
[系统触发云备份]
   ↓
EntryBackupAbility.onBackup()
   ↓
[系统触发云恢复]
   ↓
EntryBackupAbility.onRestore()

8.2 数据备份范围

玄象项目未来可在 onBackup 中备份以下数据:

  1. 用户偏好:主题色、字体大小、提醒开关。
  2. 历史记录:八字命盘、起卦历史、AI 对话记录。
  3. 会员信息:会员等级、到期时间、购买记录。

8.3 版本迁移处理

onRestore(bundleVersion) 接收 BundleVersion 参数,玄象项目可在此处理版本迁移:

async onRestore(bundleVersion: BundleVersion) {
  if (bundleVersion.versionCode < 1000002) {
    // 旧版本数据迁移逻辑
    await this.migrateOldData();
  }
  await Promise.resolve();
}

总结

本篇以玄象项目 EntryAbilityEntryBackupAbility 为蓝本,深入剖析了 HarmonyOS 应用 Ability 设计的取舍决策:单 UIAbility 的优势、EntryAbility 生命周期、EntryBackupAbility 备份扩展能力,以及未来多 Ability 拆分的设想。掌握这些决策框架,能让您在面对不同业务场景时做出合理的 Ability 设计。

下一篇:《07 · code-linter.json5 配置:ArkTS 严格模式下的代码规范》,将带您深入玄象项目的代码静态检查体系。

如果篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!


相关资源:

Logo

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

更多推荐