HarmonyOS鸿蒙Next中UIAbility的实现与应用

HarmonyOS鸿蒙Next中UIAbility的实现与应用

介绍

UIAilbity是鸿蒙开发中包含UI界面的应用程序.(也是一种组件)
主要用于和用户进行交互

UIAbility特点

1、UIAbility是系统调度的基本单元。为应用提供了绘制界面的窗口。所有页面和组件要进行渲染,必须要有一个窗口才能呈现。UIAbility提供了显示页面窗口。
2、一个UIAbility可以通过多个页面来实现一个模块功能
一个UIAbility里面可以包含很多个页面。对各UIAbility页面进行分类管理。
什么情况下出现多个UiAbility,wps这个软件,新建word一个新的窗口。新建excele又是一个新的窗口
3、每一个UIAbility的组件实例,都会对应于一个最近的任务列表中任务。

声明配置

为使应用能够正常使用UIAbility,需要在module.json5配置文件的abilities标签中声明UIAbility的名称、入口、标签等相关信息

总结:

UIAbility生命周期函数执行流程:
onCreate:代表应用初始化加载,这个生命周期函数执行代表应用正在启动。我们可以接受外部传递传递来的参数
onWindowStageCreate:代表应用创建的时候,必须创建窗口对象。用于加载我们页面的内容。开发中很多时候会在这个函数中执行数据库初始化,全局AppStorage内容的存储。
onForground:应用切换到前台。当你一个应用启动,肯定默认显示这个应用
onBackground:应用切换到后台。在手机上面退出了这个界面
onWindowStageDestry:将应用退出我们系统,先执行窗口销毁。
onDestroy:应用的销毁

页面生命周期
被entry修饰的组件我们默认就是当成页面来使用
他也是有生命周期的

创建UIAbility窗口
选中项目ets目录,右键选择创建ability
在项目中会多出一个文件夹,其中在代码中配置入口页面

其中在代码中配置入口页面

export default class PayAbility extends UIAbility {
  onWindowStageCreate(windowStage: window.WindowStage): void {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');

    windowStage.loadContent('pages01/PayPage', (err) => {
      if (err.code) {
        hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
        return;
      }
      hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');
    });
  }
}

以后支付页面就属于PayAbility下面管理的页面

在model.json5文件中

"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:white",
    "exported": true,
    "skills": [
      {
        "entities": [
          "entity.system.home"
        ],
        "actions": [
          "action.system.home"
        ]
      }
    ]
  },
  {
    "name": "PayAbility",
    "srcEntry": "./ets/payability/PayAbility.ets",
    "description": "$string:PayAbility_desc",
    "icon": "$media:layered_image",
    "label": "$string:PayAbility_label",
    "startWindowIcon": "$media:startIcon",
    "startWindowBackground": "$color:start_window_background"
  }
]

配置了两个Ability,意味着以后我们可以在项目启动的时候,指定加载那个Ability

窗口调用
不管你项目创建了多少个Ability窗口
默认进来显示第一个窗口
如何实现窗口调用
默认还是采用路由的模式来进行页面的访问

//实际上应用程序并内有实现新窗口的启动和加载,只是默认的路由页面跳转。还是在同一个窗口中
onClick() {
  router.push({
    url: "page/PayPage"
  })
}

start Ability调用窗口
在启动窗口显示的时候,官方默认提供三种模式
1、singleton: 单实例模式,一个窗口只会被创建一次。如果重复唤起窗口,会加载已经存在的这个窗口。项目中有多少个Ability,你就能打开多少个个窗口。默认如果你的代码没有设置指定模式,采用中这种模式。
2、multiton:启动模式为多实例模式,每次调用strartAbility这个函数来唤起窗口,都会创建一个新的UI Ability来实现页面的展示。
3、specified:启动模式为指定实例模式,每次strartAbility来唤起窗口的时候,你可以指定新建一个新窗口来显示还是展示用之前已经此乃在过的窗口。

  1. 配置我们Ability的启动模式
    找到module.json5文件,找到你要配置的ability,添加“launchType”:“singleton”
{
  "name": "PayAbility",
  "srcEntry": "./ets/payability/PayAbility.ets",
  "description": "$string:PayAbility_desc",
  "icon": "$media:layered_image",
  "label": "$string:PayAbility_label",
  "launchType": "singleton",
  "startWindowIcon": "$media:startIcon",
  "startWindowBackground": "$color:start_window_background"
}
  1. context的概念
    context的概念:context代表应用上下文对象,只要你的项目启动默认都会创建上下文对象。系统将很多操作都封装到这个上下文对象,比如文件操作、系统资源、窗口的信息等等封装到这个对象。
    以后代码开发过程中需要获取上面信息,都可以利用上下文对象来获取。

如果是在Ability中要获取context上下文对象我们可以直接通过

const context=this.context

如果要在页面和组件中获取context,官方给我们提供了一个getContext()来获取context

getContext(this) as common.UIAbilityContext

3)want对象
Want是一种对象,用于在应用组件之间传递信息。
目前来实现的功能,窗口之间要进行通信
解决两个痛点:我要和谁通信,我需要底层什么数据过去

指定实例模式
指定实例模式,可以允许你打开一个已经存在的窗口实例。也可以循序直接创建一个新的实例模式

1) 这个实例默认加载页面就是文档编辑页面 page/EditPage

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

export default class DocumentAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
  }

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

  onWindowStageCreate(windowStage: window.WindowStage): void {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');

    windowStage.loadContent('page/EditPage', (err) => {
      if (err.code) {
        hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
        return;
      }
      hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');
    });
  }

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

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

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

2)设置启动模式

{
  "name": "DocumentAbility",
  "srcEntry": "./ets/documentability/DocumentAbility.ets",
  "description": "$string:DocumentAbility_desc",
  "icon": "$media:layered_image",
  "label": "$string:DocumentAbility_label",
  "startWindowIcon": "$media:startIcon",
  "startWindowBackground": "$color:start_window_background",
  "launchType": "specified"   //指定实例
}

3)创建主页和编辑页面

import { common, Want } from '@kit.AbilityKit';

@Entry
@Component
struct DocumentPage {
  @State message: string = '备忘录页面';
  @State docs:Array<number>=[]
  @State index:number=1
  build() {
    Column() {
      Text(this.message)
        .fontSize(30)
        .fontWeight(FontWeight.Bold)
      Button("新建备忘录").onClick(() => {
        this.docs.push(this.index)
        let context=getContext(this) as common.UIAbilityContext
        let want:Want={
          deviceId:'',
          bundleName:'com.hakuna.test',
          abilityName:'DocumentAbility'
        }
        context.startAbility(want,(err)=>{
          if(err){
            console.log(`${err.code}`)
          }
        })
      })
      Column(){
        List(){
          ForEach(this.docs,(item:number,index:number)=>{
            ListItem(){
              Row(){
                Image($r('app.media.app_icon'))
                  .width(40)
                Text(`备忘录${item}`)
              }
              .onClick(()=>{
                let context=getContext(this) as common.UIAbilityContext
                let want:Want={
                  deviceId:'',
                  bundleName:'com.hakuna.test',
                  abilityName:'DocumentAbility',
                  parameters:{
                    instanceKey:`idx_${index+1}`
                  }
                }
                context.startAbility(want,(err)=>{
                  if(err){
                    console.log(`${err.code}`)
                  }
                })
              })
            }
          },(item:number)=>`${item}`)
        }
      }
    }
    .height('100%')
    .width('100%')
  }
}

EditPage.ets这个页面负责编辑内容

@Entry
@Component
struct EditPage {
  @State message: string = '编辑备忘录';

  build() {
    RelativeContainer() {
      Text(this.message)
        .id('EditPageHelloWorld')
        .fontSize(50)
        .fontWeight(FontWeight.Bold)
        .alignRules({
          center: { anchor: '__container__', align: VerticalAlign.Center },
          middle: { anchor: '__container__', align: HorizontalAlign.Center }
        })
      TextInput({placeholder:'请输入编辑内容'})
    }
    .height('100%')
    .width('100%')
  }
}

4)配置AbilityStage容器
现在页面中会创建多个documentAbility窗口,如果你想要控制documentAbility窗口显示,那就必须用AbilityStage来控制。
在module.json5文件中

{
  "module": {
    "name": "default",
    "type": "entry",
    "description": "$string:module_desc",
    "srcEntry": "./ets/myabilitystage/MyAbilityStage.ets",
    "mainElement": "EntryAbility",
    "deviceTypes": [
      "phone",
      "tablet",
      "2in1"
    ],

在documentPage页面中

import { common, Want } from '@kit.AbilityKit';

@Entry
@Component
struct DocumentPage {
  @State message: string = '备忘录页面';
  @State docs:Array<number>=[]
  @State index:number=1
  build() {
    Column() {
      Text(this.message)
        .fontSize(30)
        .fontWeight(FontWeight.Bold)
      Button("新建备忘录").onClick(() => {
        this.docs.push(this.index)
        let context=getContext(this) as common.UIAbilityContext
        let want:Want={
          deviceId:'',
          bundleName:'com.hakuna.test',
          abilityName:'DocumentAbility',
          parameters:{
            instanceKey:`idx_${this.index++}`
          }
        }
        context.startAbility(want,(err)=>{
          if(err){
            console.log(`${err.code}`)
          }
        })
      })
      Column(){
        List(){
          ForEach(this.docs,(item:number,index:number)=>{
            ListItem(){
              Row(){
                Image($r('app.media.app_icon'))
                  .width(40)
                Text(`备忘录${item}`)
              }
              .onClick(()=>{
                let context=getContext(this) as common.UIAbilityContext
                let want:Want={
                  deviceId:'',
                  bundleName:'com.hakuna.test',
                  abilityName:'DocumentAbility',
                  parameters:{
                    instanceKey:`idx_${index+1}`
                  }
                }
                context.startAbility(want,(err)=>{
                  if(err){
                    console.log(`${err.code}`)
                  }
                })
              })
            }
          },(item:number)=>`${item}`)
        }
      }
    }
    .height('100%')
    .width('100%')
  }
}

Row组件中的onClick这个事件,点击过后跳转到documentAbility传递了参数parameters

parameters:{
  instanceKey:`idx_${index+1}`
}

更多关于HarmonyOS鸿蒙Next中UIAbility的实现与应用的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

HarmonyOS鸿蒙Next中的UIAbility是应用的基本组成单元,负责管理用户界面和生命周期。UIAbility通过AbilitySlice实现界面跳转和逻辑处理,支持多窗口、分屏等特性。开发者可通过onCreateonStart等生命周期回调管理界面状态。UIAbility与Page Ability类似,但更注重界面与逻辑的分离,提升开发效率。

更多关于HarmonyOS鸿蒙Next中UIAbility的实现与应用的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,UIAbility是应用与用户交互的核心组件,作为系统调度的基本单元,它负责管理应用窗口和页面生命周期。以下是关键点总结:

核心特性:

  • 提供绘制界面的窗口容器
  • 支持多页面管理(一个UIAbility可包含多个页面)
  • 每个实例对应任务列表中的一个独立任务

生命周期管理:

  • onCreate:初始化应用资源
  • onWindowStageCreate:创建窗口并加载页面内容
  • onForeground/onBackground:处理前后台切换
  • 完整生命周期图示清晰展示了状态流转

配置声明:

需在module.json5中声明ability信息,包括:

{
  "abilities": [{
    "name": "EntryAbility",
    "srcEntry": "./ets/entryability/EntryAbility.ets",
    "launchType": "singleton" // 启动模式
  }]
}

启动模式:

  • Singleton:单例模式(默认)
  • Multiton:多实例模式
  • Specified:指定实例模式(需配合AbilityStage实现)

窗口调用:

通过Want对象指定目标ability:

const want = {
  bundleName: 'com.example.app',
  abilityName: 'PayAbility'
}
context.startAbility(want)

上下文获取:

  • Ability内:直接使用this.context
  • 页面/组件:通过getContext()获取

对于指定实例模式,需在AbilityStage中实现onAcceptWant方法处理实例标识,实现精细化窗口管理。实际开发中,合理选择启动模式对多任务场景尤为重要。

回到顶部