鸿蒙开发笔记-12-浅析UIAbility组件

31 阅读4分钟
  • Ability Kit(程序框架服务)提供了应用程序开发和运行的应用模型,是系统为开发者提供的应用程序所需能力的抽象提炼,它提供了应用程序必备的组件和运行机制。

应用模型

  • 随着系统的演进发展,先后提供了两种应用模型:
  1. FA(Feature Ability)模型:从API 7开始支持的模型,已经不再主推。
  2. Stage模型:从API 9开始新增的模型,是目前主推且会长期演进的模型。在该模型中,由于提供了AbilityStage、WindowStage等类作为应用组件和Window窗口的“舞台”,因此称这种应用模型为Stage模型。
  • Stage模型概念图: Stage模型概念图
  • Stage模型有三类进程:1. 主进程 2. ExtensionAbility进程 3. 渲染进程
  • AbilityStage: 每个Entry类型或者Feature类型的HAP在运行期都有一个AbilityStage类实例。
  • UIAbility组件:是一种包含UI的应用组件,主要用于和用户交互。
  • ExtensionAbility组件:是一种面向特定场景的应用组件。开发者并不直接从ExtensionAbility组件派生,而是需要使用ExtensionAbility组件的派生类。
  • WindowStage:每个UIAbility实例都会与一个WindowStage类实例绑定,该类起到了应用进程内窗口管理器的作用。
  • Context:在Stage模型上,Context及其派生类向开发者提供在运行期可以调用的各种资源和能力。

UIAbility组件概述

UIAbility是HarmonyOS应用框架的核心组件,负责管理用户界面与系统资源的交互。其核心设计理念包括:

  • 跨端迁移:支持应用组件在不同设备间无缝迁移
  • 多端协同:实现多窗口、多任务并行处理
  • 窗口管理:每个UIAbility实例对应一个独立任务窗口, 支持单实例/多实例运行模式
  • 生命周期感知:提供完整的生命周期回调体系
  • 多模块交互:支持与Service/ExtensionAbility深度协作
  • 状态可移植:通过统一的上下文管理机制(UIAbilityContext)实现运行状态的持久化存储与恢复
  • 原子化调度:系统调度的最小单位,支持独立部署与运行
  • UI容器属性:通过WindowStage管理ArkUI页面栈

声明配置示例(module.json5):

{
  "module": {
    "abilities": [
      {
        "name": "EntryAbility", // UIAbility组件的名称
        "launchType": "singleton", //启动模式
        "srcEntry": "./ets/entryability/EntryAbility.ets", // UIAbility组件的代码路径
        "description": "$string:EntryAbility_desc",// UIAbility组件的描述信息
        "icon": "$media:layered_image",// UIAbility组件的图标
        "label": "$string:EntryAbility_label", // UIAbility组件的标签
        "startWindowIcon": "$media:startIcon", // UIAbility组件启动页面图标资源文件的索引
        "startWindowBackground": "$color:start_window_background",// UIAbility组件启动页面背景颜色资源文件的索引
        "exported": true,
      }
    ]
  }
}

生命周期管理

生命周期状态机包含6种状态:Create → WindowStageCreate → Foreground → Background → WindowStageDestroy → Destroy

创建阶段

export default class MainAbility extends UIAbility {
  onCreate(want: Want, launchParam: LaunchParam) {
    console.log("Ability创建");
    // 初始化全局资源
    this.globalData = { count: 0 };
  }
}

窗口阶段

onWindowStageCreate(windowStage: WindowStage) {
  console.log("窗口创建完成");
  // 加载主页面
  windowStage.loadContent('pages/Index', (err) => {
    if (err) console.error('加载失败:', err);
  });
  
  // 监听窗口事件
  windowStage.on('windowStageEvent', (event) => {
    switch(event) {
      case WindowStageEventType.SHOWN:
        this.handleWindowFocus();  
        break;
      case 'ACTIVE':
        console.log('窗口获取焦点');
        break;
      case 'INACTIVE':
        console.log('窗口失去焦点');
        break;
    }
  });
}

onWindowStageWillDestroy(windowStage: window.WindowStage) {
    // 释放通过windowStage对象获取的资源
}

onWindowStageDestroy(): void {
    // 释放UI资源
    // 例如在onWindowStageDestroy()中注销获焦/失焦等WindowStage事件
}

前后台切换

onForeground() {
  console.log("进入前台");
  // 申请定位权限等前台资源
  requestLocationPermission();
}

onBackground() {
  // 释放内存资源
  this.globalData = null;
}

销毁阶段

onDestroy() {
  console.log("Ability销毁");
  // 清理残留资源
  if (this.timer) {
    clearInterval(this.timer);
  }
}

启动模式

模式特性使用场景
singleton默认,单实例,主界面/全局服务
multiton多实例,独立运行并行任务处理
specified指定Key标识实例文档编辑器等场景

1. singleton启动模式:

  • 单实例模式(默认),共享同一上下文。
  • 每次调用startAbility()方法时,如果应用进程中该类型的UIAbility实例已经存在,则复用系统中的UIAbility实例。
  • 系统中只存在唯一一个该UIAbility实例,即在最近任务列表中只存在一个该类型的UIAbility实例。(进入该UIAbility的onNewWant()回调)
  • 当应用的UIAbility实例已创建,且UIAbility配置为singleton启动模式时,再次调用startAbility()方法启动该UIAbility实例时,只会进入该UIAbility的onNewWant()回调,不会进入其onCreate()和onWindowStageCreate()生命周期回调。应用可以在该回调中更新要加载的资源和数据等,用于后续的UI展示。

2. multiton启动模式:

  • 多实例模式。
  • 每次调用startAbility()方法时,都会在应用进程中创建一个新的该类型UIAbility实例。即在最近任务列表中可以看到有多个该类型的UIAbility实例。

3. specified启动模式:

  • 指定实例模式,针对一些特殊场景使用(例如文档应用中每次新建文档希望都能新建一个文档实例,重复打开一个已保存的文档希望打开的都是同一个文档实例)。
  • 在创建UIAbility实例之前,开发者可以为该实例指定一个唯一的字符串Key,这样在调用startAbility()方法时,应用就可以根据指定的Key来识别响应请求的UIAbility实例。在EntryAbility中,调用startAbility()方法时,可以在want参数中增加一个自定义参数,例如instanceKey,以此来区分不同的UIAbility实例。
// AbilityStage实现
export default class MyAbilityStage extends AbilityStage {
  onAcceptWant(want: Want): string {
    return `SPEC_KEY_${want.parameters.docId}`;
  }
}

// 启动时指定Key
let want = {
  abilityName: 'SpecifiedAbility',
  parameters: { docId: 'DOC_2023' }
};

数据同步机制

EventHub事件总线

// 发布事件
this.context.eventHub.emit('userUpdated', { id: 1, name: 'Alice' });

// 订阅事件
this.context.eventHub.on('userUpdated', (user) => {
  console.log('用户信息更新:', user);
});

应用级存储

// 全局存储(跨Ability)
AppStorage.set('userInfo', { token: 'abc123' });

// 局部存储(当前Ability)
LocalStorage.set('settings', { theme: 'dark' });

跨Ability交互

参数传递

// 启动时传递参数
let want = {
  abilityName: 'DetailAbility',
  parameters: { id: 123, type: 'video' }
};

// 接收参数
export default class DetailAbility extends UIAbility {
  onCreate(want: Want) {
    let params = want.parameters;
    console.log('接收参数:', params.id, params.type);
  }
}

结果回调

// 发起请求
startAbilityForResult(want).then((result) => {
  console.log('返回数据:', result.data);
});

// 返回结果
terminateSelfWithResult({
  resultCode: 200,
  want: {
    parameters: { success: true }
  }
});

实战技巧

启动UIAbility的指定页面

  • 一个UIAbility可以对应多个页面,在不同的场景下启动该UIAbility时需要展示不同的页面。
  • UIAbility的启动分为两种情况:UIAbility冷启动和UIAbility热启动。
    1. UIAbility冷启动:指的是UIAbility实例处于完全关闭状态下被启动,这需要完整地加载和初始化UIAbility实例的代码、资源等。
    2. UIAbility热启动:指的是UIAbility实例已经启动并在前台运行过,由于某些原因切换到后台,再次启动该UIAbility实例,这种情况下可以快速恢复UIAbility实例的状态。
  • 调用方UIAbility指定启动页面:通过want中的parameters参数增加一个自定义参数传递页面跳转信息。
// 冷启动指定页面
if (this.isColdStart) {
  windowStage.loadContent('pages/Login');
} else {
  router.pushUrl({ url: 'pages/Dashboard' });
}

// 热启动页面跳转
this.router.replaceUrl({ url: 'pages/Profile' });

错误处理

try {
  await this.context.startAbility(want);
} catch (err) {
  if (err.code === 1008500011) {
    showToast('文件传输权限不足');
  } else {
    console.error('启动失败:', err);
  }
}
  • 通过掌握UIAbility的生命周期管理、启动模式配置、数据同步机制及跨组件交互技巧,开发者可以构建高效、灵活的HarmonyOS应用架构,实现真正的分布式能力。

我是今阳,如果想要进阶和了解更多的干货,欢迎关注微信公众号 “今阳说” 接收我的最新文章