【最新鸿蒙应用开发】——一篇读懂UIAbility是什么?作用?

UIAbility组件

UIAbility组件是一种包含UI的应用组件,UIAbility组件是系统调度的基本单元(最小单元),为应用提供绘制界面的窗口,主要用于和用户交互。一个应用可以包含一个或多个UIAbility组件。

UIAbility的设计理念:

  1. 原生支持应用组件级的跨端迁移和多端协同。
  2. 支持多设备和多窗口形态。

UIAbility划分原则与建议:

UIAbility组件是系统调度的基本单元,为应用提供绘制界面的窗口。一个应用可以包含一个或多个UIAbility组件。例如,在支付应用中,可以将入口功能和收付款功能分别配置为独立的UIAbility。

每一个UIAbility组件实例都会在最近任务列表中显示一个对应的任务。

对于开发者而言,可以根据具体场景选择单个还是多个UIAbility,划分建议如下:

  • 如果开发者希望在任务视图中看到一个任务,则建议使用一个UIAbility,多个页面的方式。
  • 如果开发者希望在任务视图中看到多个任务,或者需要同时开启多个窗口,则建议使用多个UIAbility开发不同的模块功能。

一、声明配置

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

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

二、UIAbility生命周期状态

当用户打开、切换和返回到对应应用时,应用中的UIAbility实例会在其生命周期的不同状态之间转换。UIAbility类提供了一系列回调,通过这些回调可以知道当前UIAbility实例的某个状态发生改变,会经过UIAbility实例的创建和销毁,或者UIAbility实例发生了前后台的状态切换。

UIAbility的生命周期包括Create、Foreground、Background、Destroy四个状态,如下图所示。

Create状态

Create状态为在应用加载过程中,UIAbility实例创建完成时触发,系统会调用onCreate()回调。可以在该回调中进行页面初始化操作,例如变量定义资源加载等,用于后续的UI展示。

ts 复制代码
import type AbilityConstant from '@ohos.app.ability.AbilityConstant';
import UIAbility from '@ohos.app.ability.UIAbility';
import type Want from '@ohos.app.ability.Want';
​
export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    // 页面初始化
  }
  // ...
}
ts

说明

Want是对象间信息传递的载体,可以用于应用组件间的信息传递。Want的详细介绍请参见信息传递载体Want

WindowStageCreate和WindowStageDestroy状态

UIAbility实例创建完成之后,在进入Foreground之前,系统会创建一个WindowStage。WindowStage创建完成后会进入onWindowStageCreate()回调,可以在该回调中设置UI加载、设置WindowStage的事件订阅。

WindowStageCreate和WindowStageDestroy状态

在onWindowStageCreate()回调中通过loadContent()方法设置应用要加载的页面,并根据需要调用on('windowStageEvent')方法订阅WindowStage的事件(获焦/失焦、可见/不可见)。

ts 复制代码
import UIAbility from '@ohos.app.ability.UIAbility';
import window from '@ohos.window';
​
export default class EntryAbility extends UIAbility {
  // ...
  onWindowStageCreate(windowStage: window.WindowStage): void {
    // 设置WindowStage的事件订阅(获焦/失焦、可见/不可见)
    try {
      windowStage.on('windowStageEvent', (data) => {
        let stageEventType: window.WindowStageEventType = data;
        switch (stageEventType) {
          case window.WindowStageEventType.SHOWN: // 切到前台
            console.info('windowStage foreground.');
            break;
          case window.WindowStageEventType.ACTIVE: // 获焦状态
            console.info('windowStage active.');
            break;
          case window.WindowStageEventType.INACTIVE: // 失焦状态
            console.info('windowStage inactive.');
            break;
          case window.WindowStageEventType.HIDDEN: // 切到后台
            console.info('windowStage background.');
            break;
          default:
            break;
        }
      });
    } catch (exception) {
      console.error('Failed to enable the listener for window stage event changes. Cause:' + JSON.stringify(exception));
    }
    // 设置UI加载
    windowStage.loadContent('pages/Index', (err, data) => {
      // ...
    });
  }
}
ts

对应于onWindowStageCreate()回调。在UIAbility实例销毁之前,则会先进入onWindowStageDestroy()回调,可以在该回调中释放UI资源。

ts 复制代码
import UIAbility from '@ohos.app.ability.UIAbility';
import window from '@ohos.window';
​
export default class EntryAbility extends UIAbility {
  windowStage: window.WindowStage | undefined = undefined;
  // ...
  onWindowStageCreate(windowStage: window.WindowStage): void {
    this.windowStage = windowStage;
    // ...
  }
  onWindowStageDestroy() {
    // 释放UI资源
  }
}
ts

Foreground和Background状态

Foreground和Background状态分别在UIAbility实例切换至前台和切换至后台时触发,对应于onForeground()回调和onBackground()回调。

onForeground()回调,在UIAbility的UI可见之前,如UIAbility切换至前台时触发。可以在onForeground()回调中申请系统需要的资源,或者重新申请在onBackground()中释放的资源。

onBackground()回调,在UIAbility的UI完全不可见之后,如UIAbility切换至后台时候触发。可以在onBackground()回调中释放UI不可见时无用的资源,或者在此回调中执行较为耗时的操作,例如状态保存等。

例如应用在使用过程中需要使用用户定位时,假设应用已获得用户的定位权限授权。在UI显示之前,可以在onForeground()回调中开启定位功能,从而获取到当前的位置信息。

当应用切换到后台状态,可以在onBackground()回调中停止定位功能,以节省系统的资源消耗。

ts 复制代码
import UIAbility from '@ohos.app.ability.UIAbility';
​
export default class EntryAbility extends UIAbility {
  // ...
​
  onForeground(): void {
    // 申请系统需要的资源,或者重新申请在onBackground()中释放的资源
  }
​
  onBackground(): void {
    // 释放UI不可见时无用的资源,或者在此回调中执行较为耗时的操作
    // 例如状态保存等
  }
}
ts

当应用的UIAbility实例已创建,且UIAbility配置为singleton启动模式时,再次调用startAbility()方法启动该UIAbility实例时,只会进入该UIAbility的onNewWant()回调,不会进入其onCreate()onWindowStageCreate()生命周期回调。应用可以在该回调中更新要加载的资源和数据等,用于后续的UI展示。

ts 复制代码
import type AbilityConstant from '@ohos.app.ability.AbilityConstant';
import UIAbility from '@ohos.app.ability.UIAbility';
import type Want from '@ohos.app.ability.Want';
​
export default class EntryAbility extends UIAbility {
  // ...
​
  onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam) {
    // 更新资源、数据
  }
}
ts

Destroy状态

Destroy状态在UIAbility实例销毁时触发。可以在onDestroy()回调中进行系统资源的释放、数据的保存等操作。

例如调用terminateSelf()方法停止当前UIAbility实例,从而完成UIAbility实例的销毁;或者用户使用最近任务列表关闭该UIAbility实例,完成UIAbility的销毁。

ts 复制代码
import UIAbility from '@ohos.app.ability.UIAbility';
​
export default class EntryAbility extends UIAbility {
  // ...
​
  onDestroy() {
    // 系统资源的释放、数据的保存等
  }
}

三、UIAbility组件启动模式

UIAbility的启动模式是指UIAbility实例在启动时的不同呈现状态。针对不同的业务场景,系统提供了三种启动模式:

singleton启动模式

singleton启动模式为单实例模式,也是默认情况下的启动模式。

每次调用startAbility()方法时,如果应用进程中该类型的UIAbility实例已经存在,则复用系统中的UIAbility实例。系统中只存在唯一一个该UIAbility实例,即在最近任务列表中只存在一个该类型的UIAbility实例。

multiton启动模式

multiton启动模式为多实例模式,每次调用startAbility()方法时,都会在应用进程中创建一个新的该类型UIAbility实例。即在最近任务列表中可以看到有多个该类型的UIAbility实例。这种情况下可以将UIAbility配置为multiton(多实例模式)。

specified启动模式

specified启动模式为指定实例模式,针对一些特殊场景使用(例如文档应用中每次新建文档希望都能新建一个文档实例,重复打开一个已保存的文档希望打开的都是同一个文档实例)。

指定UIAbility的启动页面

应用中的UIAbility在启动过程中,需要指定启动页面,否则应用启动后会因为没有默认加载页面而导致白屏。可以在UIAbility的onWindowStageCreate()生命周期回调中,通过WindowStage对象的loadContent()方法设置启动页面。

ts 复制代码
import UIAbility from '@ohos.app.ability.UIAbility';
import window from '@ohos.window';
​
export default class EntryAbility extends UIAbility {
  onWindowStageCreate(windowStage: window.WindowStage): void {
    // Main window is created, set main page for this ability
    windowStage.loadContent('pages/Index', (err, data) => {
      // ...
    });
  }
  // ...
}

获取UIAbility的上下文信息

UIAbility类拥有自身的上下文信息,该信息为UIAbilityContext类的实例,UIAbilityContext类拥有abilityInfo、currentHapModuleInfo等属性。通过UIAbilityContext可以获取UIAbility的相关配置信息,如包代码路径、Bundle名称、Ability名称和应用程序需要的环境状态等属性信息,以及可以获取操作UIAbility实例的方法(如startAbility()connectServiceExtensionAbility()terminateSelf()等)。 如果需要在页面中获得当前Ability的Context,可调用getContext接口获取当前页面关联的UIAbilityContext或ExtensionContext。

  • 在UIAbility中可以通过this.context获取UIAbility实例的上下文信息。

    ts 复制代码
    import UIAbility from '@ohos.app.ability.UIAbility';
    import AbilityConstant from '@ohos.app.ability.AbilityConstant';
    import Want from '@ohos.app.ability.Want';
    ​
    export default class EntryAbility extends UIAbility {
      onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
        // 获取UIAbility实例的上下文
        let context = this.context;
        // ...
      }
    }
    ts
  • 在页面中获取UIAbility实例的上下文信息,包括导入依赖资源context模块和在组件中定义一个context变量两个部分。

    ts 复制代码
    import common from '@ohos.app.ability.common';
    import Want from '@ohos.app.ability.Want';
    ​
    @Entry
    @Component
    struct Index {
      private context = getContext(this) as common.UIAbilityContext;
    ​
      startAbilityTest() {
        let want: Want = {
          // Want参数信息
        };
        this.context.startAbility(want);
      }
    ​
      // 页面展示
      build() {
        // ...
      }
    }
    ts

    也可以在导入依赖资源context模块后,在具体使用UIAbilityContext前进行变量定义。

    ts 复制代码
    import common from '@ohos.app.ability.common';
    import Want from '@ohos.app.ability.Want';
    ​
    @Entry
    @Component
    struct Index {
    ​
      startAbilityTest() {
        let context = getContext(this) as common.UIAbilityContext;
        let want: Want = {
          // Want参数信息
        };
        context.startAbility(want);
      }
    ​
      // 页面展示
      build() {
        // ...
      }
    }

四、UIAbility组件与UI的数据同步

基于当前的应用模型,可以通过以下几种方式来实现UIAbility组件与UI之间的数据同步。

  • 使用EventHub进行数据通信:在基类Context中提供了EventHub对象,可以通过发布订阅方式来实现事件的传递。在事件传递前,订阅者需要先进行订阅,当发布者发布事件时,订阅者将接收到事件并进行相应处理。
  • 使用AppStorage/LocalStorage进行数据同步:ArkUI提供了AppStorage和LocalStorage两种应用级别的状态管理方案,可用于实现应用级别和UIAbility级别的数据同步。

五、UIAbility组件间交互(设备内)

UIAbility是系统调度的最小单元。在设备内的功能模块之间跳转时,会涉及到启动特定的UIAbility,该UIAbility可以是应用内的其他UIAbility,也可以是其他应用的UIAbility(例如启动三方支付UIAbility)。

本文将从如下场景分别介绍设备内UIAbility间的交互方式。对于跨设备的应用组件交互,请参见应用组件跨设备交互(流转)

三方应用调用系统应用,对于ability的交互和传值有什么限制?除了数据大小方面

重点介绍自己对ability的理解,描述显式want和隐式want的区别,带入到对应面试项目中场景来 启动应用内的UIAbility 启动应用内的UIAbility并获取返回结果 启动其他应用的UIAbility 启动其他应用的UIAbility并获取返回结果 启动UIAbility的指定页面 显式Want启动:在want参数中需要设置该应用bundleName和abilityName,当需要拉起某个明确的UIAbility时,通常使用显式Want启动方式。 隐式Want启动:不明确指出要启动哪一个UIAbility,在调用startAbility()方法时,其入参want中指定了一系列的entities字段(表示目标UIAbility额外的类别信息,如浏览器、视频播放器)和actions字段(表示要执行的通用操作,如查看、分享、应用详情等)等参数信息,然后由系统去分析want,并帮助找到合适的UIAbility来启动。

三方应用调用系统应用, 需要用到want , want分为显示和隐式

  • 显式Want:在启动目标应用组件时,调用方传入的want参数中指定了abilityName和bundleName,称为显式Want。

    ts 复制代码
    //这个代码可以不用详细介绍,不然就跑题了,这里给大家提供代码是为了方便大家回顾
    import Want from '@ohos.app.ability.Want';
    ​
    let wantInfo: Want = {
      deviceId: '', // deviceId为空表示本设备
      bundleName: 'com.example.myapplication',
      abilityName: 'FuncAbility',
    }
  • 隐式Want:在启动目标应用组件时,调用方传入的want参数中未指定abilityName,称为隐式Want。

    ts 复制代码
    //这个代码可以不用详细介绍,不然就跑题了,这里给大家提供代码是为了方便大家回顾
    import Want from '@ohos.app.ability.Want';
    ​
    let wantInfo: Want = {
      // uncomment line below if wish to implicitly query only in the specific bundle.
      // bundleName: 'com.example.myapplication',
      action: 'ohos.want.action.search',
      // entities can be omitted
      entities: [ 'entity.system.browsable' ],
      uri: 'https://www.test.com:8080/query/student',
      type: 'text/plain',
    };
    • 在调用startAbility()方法时,其入参want中指定了一系列的entities字段(表示目标UIAbility额外的类别信息,如浏览器、视频播放器)和actions字段(表示要执行的通用操作,如查看、分享、应用详情等)等参数信息,
    • 然后由系统去分析want,并帮助找到合适的UIAbility来启动。

关于传值, 我之前做过授权的功能 , 如果用户第一次拒绝授权,第二次再次进去此页面,则可以直接引导用户调到应用设置界面

对数据类型的限制,目前支持的数据类型有:字符串、数字、布尔、对象、数组和文件描述符等。

参考文献: UIAbility组件概述 (openharmony.cn)

相关推荐
鸿蒙布道师1 分钟前
鸿蒙NEXT开发对象工具类(TS)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
zhang1062093 分钟前
HarmonyOS 基础组件和基础布局的介绍
harmonyos·基础组件·基础布局
马剑威(威哥爱编程)16 分钟前
在HarmonyOS NEXT 开发中,如何指定一个号码,拉起系统拨号页面
华为·harmonyos·arkts
GeniuswongAir2 小时前
Flutter极速接入IM聊天功能并支持鸿蒙
flutter·华为·harmonyos
90后的晨仔5 小时前
鸿蒙ArkUI框架中的状态管理
harmonyos
别说我什么都不会21 小时前
OpenHarmony 5.0(API 12)关系型数据库relationalStore 新增本地数据变化监听接口介绍
api·harmonyos
MardaWang1 天前
HarmonyOS 5.0.4(16) 版本正式发布,支持wearable类型的设备!
华为·harmonyos
余多多_zZ1 天前
鸿蒙学习手册(HarmonyOSNext_API16)_应用开发UI设计:Swiper
学习·ui·华为·harmonyos·鸿蒙系统
斯~内克1 天前
鸿蒙网络通信全解析:从网络状态订阅到高效请求实践
网络·php·harmonyos
别说我什么都不会1 天前
OpenHarmony 5.0Release 开发的在线音乐应用卡片
app·harmonyos