鸿蒙5:HarmonyOS应用开发-UIAbility组件

91 阅读7分钟

1. UIAbility 组件

每一个UIAbility实例,都对应于一个最近任务列表中的任务。

UIAbility是一种包含用户界面的应用组件,主要用于和用户进行交互。UIAbility也是系统调度的单元,为应用提供窗口在其中绘制界面。

编辑

一个应用可以有一个 UIAbility也可以有多个UIAbility,如图所示:

  • 单 UIAbility:任务列表只有一个任务,应用内部结合【多页面】的形式让用户进行的搜索和浏览内容,页面的跳转使用路由来实现即可(到目前为止咱们做的都是这种)
  • 多个 UIAbility:那么在任务列表中会有多个任务。比如图片中聊天应用增加一个“外卖功能”的场景,则可以将聊天应用中“外卖功能”的内容独立为一个UIAbility,当用户打开聊天应用的“外卖功能”,查看外卖订单详情,此时有新的聊天消息,即可以通过最近任务列表切换回到聊天窗口继续进行聊天对话。

1.1 指定 UIAbility 的启动页面

在UIAbility的onWindowStageCreate()生命周期回调中,通过 WindowStage 对象的 loadContent() 方法设置启动页面。

TIP

  • 如果应用启动出现白屏,可能是加载的页面设置出现问题
  • 设置的页面,需要在 main_page.json5 中存在,且同名

编辑

onWindowStageCreate(windowStage: window.WindowStage): void {
  // Main window is created, set main page for this ability
  hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');

  windowStage.loadContent('pages/AppStorageCase01', (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.');
  });
}

注意:

  1. windowStage.loadContent加载的页面,不可以用 / 开头
  2. 加载的页面需要在 main_pages.json5 中存在
  3. 出现页面白色的(上述 2 个问题)

1.2 UIAbility 组件的生命周期

当用户打开、切换和返回到对应应用时,应用中的UIAbility实例会在其生命周期的不同状态之间转换。UIAbility类提供了一系列【回调函数】,如果需要在特定的时间添加自定义逻辑,往对应的回调函数内添加代码即可

tips:

  1. 回调函数由【开发者注册】
  2. 回调函数由【系统调用】,并且会传入对应的参数

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

编辑

  • onCreate:Ability创建时回调,执行初始化业务逻辑操作。
  • onDestory:Ability生命周期回调,在销毁时回调,执行资源清理等操作。
  • onWindowStageCreate:当WindowStage创建后调用。
  • onWindowStageDestory:当WindowStage销毁后调用。
  • onForeground:Ability生命周期回调,当应用从后台转到前台时触发。
  • onBackground:Ability生命周期回调,当应用从前台转到后台时触发。

可以根据下图的方式观察到状态改变时触发的回调函数函数:

注:

  • 3 下方划横线的内容需要手动输入

编辑

1.3 UIAbility 组件间交互

UIAbility是【系统调度】的最小单元。在设备内的功能模块之间跳转时,会涉及到启动特定的UIAbility,咱们来看看如何实现。【注:咱们目前专注于启动应用内的 UIAbility 即可】

编辑

多个 Ability 的应用

编辑

1.3.1 创建多个 Ability

首先在项目中创建多个 Ability

编辑

编辑

创建完毕之后项目会发生如下改变:

编辑

1.3.2 如何设置默认启动的 Ability

如果希望刚刚创建的Ability 作为默认启动的 Ability 可以通过如下方式进行设置:

  1. 调整配置:
    1. 配置中增加:exported 和 skills ,并移除默认Ability 中对应的配置
  1. 调整顺序:
    1. 如果多个 Ability 中都设置了exported 和 skills ,那么调整他们在 abilities 数组中的顺序即可,排名靠前的先启动
{
  "module": {
    // ....
    "abilities": [
      // 默认的 Ability
      {
        "name": "EntryAbility",
        "srcEntry": "./ets/entryability/EntryAbility.ets",
        "description": "$string:EntryAbility_desc",
        "icon": "$media:icon",
        "label": "$string:EntryAbility_label",
        "startWindowIcon": "$media:startIcon",
        "startWindowBackground": "$color:start_window_background",
      },
      {
        "name": "SecondAbility",
        "srcEntry": "./ets/secondability/SecondAbility.ets",
        "description": "$string:SecondAbility_desc",
        "icon": "$media:icon",
        "label": "$string:SecondAbility_label",
        "startWindowIcon": "$media:startIcon",
        "startWindowBackground": "$color:start_window_background",
        "exported": true,
        "skills": [
          {
            "entities": [
              "entity.system.home"
            ],
            "actions": [
              "action.system.home"
            ]
          }
        ]
      }
    ],
    "requestPermissions": [
      {
        "name": "ohos.permission.INTERNET",
        "usedScene": {
          "abilities": [
            "FormAbility"
          ],
          "when": "inuse"
        }
      }
    ],
    "extensionAbilities": [

    ]
  }
}

1.3.3 启动 UIAbility

刚刚演示的是设置默认启动的 UIAbility,接下来演示如何在应用逻辑中,通过【代码启动】

启动 UIAbility 的话,咱们分为 2 种情况:

  1. 启动同一个模块中的其他 UIAbility(目前代码的情况)
  2. 启动不同模块中的 UIAbility
1.3.3.1 同一个模块中的 UIAbility

同一个模块中的UIAbility跳转

编辑

这部分代码能够 C+V 并且【调整】为需要的值即可:

  1. 准备 want 作为 UIAbility 的启动入口参数,然后设置对应的属性值
  2. 通过 this.context获取当前 UIAbility 的【上下文对象】,然后调用 startAbility 并传入 want 即可实现启动

上下文对象:其提供了应用的一些【基础信息】和一些可以【调用的方法】

试一试:

  1. 从上一步【 添加的Abilty】 跳转到【默认的 Ability】
import { common, Want } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';

@Entry
  @Component
  struct SecondAbilityPage {
    @State message: string = 'Hello World';
    //1. 获取上下文对象(后续直接使用)
    context = getContext(this) as common.UIAbilityContext;

    build() {
      Row() {
        Column() {
          Text(this.message)
            .fontSize(50)
            .fontWeight(FontWeight.Bold)
            .onClick(() => {
              //2. 准备 want类型的对象并设置属性
              let wantInfo: Want = {
                deviceId: '', // deviceId为空表示本设备
                bundleName: 'com.example.day07', // AppScope/app.json5确认
                moduleName: 'entry', // moduleName非必选
                abilityName: 'EntryAbility', //  src/main/module.json5确认
                parameters: {
                  // 自定义信息
                  info: '来自EntryAbility Page_UIAbilityComponentsInteractive页面'
                },
              }
              //3. 通过上下文对象拉起对应的 Abilit
              this.context.startAbility(wantInfo)
                .then(() => {
                  console.log('startAbility success.');
                })
                .catch((error: BusinessError) => {
                  console.log('startAbility failed.');
                });
            })
        }
        .width('100%')
      }
      .height('100%')
        .backgroundColor(Color.Orange)
    }
  }

1.3.3.2 不同模块中的 UIAbility(了解)

上一节演示的方法因为是在同一个模块中的中的 UIAbility,虽然 UIAbility 不同,但是页面放置的文件夹是一样的,都在 Pages 里面。如果想要 把 Pages 再分开,可以通过分模块的方式来实现

  1. 创建模块

编辑

编辑

编辑

编辑

编辑

  1. 调整新创建模块内部的页面内容
@Entry
@Component
struct Index {
  build() {
    Row() {
      Column() {
        Text('其他模块的页面')
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
      }
      .width('100%')
    }
    .height('100%')
    .backgroundColor('#0094ff')
  }
}

编辑

编辑

现在项目中有多个模块,需要在编辑配置中将多个模块都勾选上

  1. 在原模块中跳转到 新创建模块中的 UIAbility
import common from '@ohos.app.ability.common';
import Want from '@ohos.app.ability.Want';
import { BusinessError } from '@ohos.base';


@Entry
@Component
struct Page_UIAbilityComponentsInteractive {
  private context = getContext(this) as common.UIAbilityContext;

  build() {
    Button('跳转到另外的 Ability')
      .onClick(() => {
        // context为Ability对象的成员,在非Ability对象内部调用需要
        // 将Context对象传递过去
        let wantInfo: Want = {
          deviceId: '', // deviceId为空表示本设备
          bundleName: 'com.example.day07',
          moduleName: 'secondApplication', // moduleName非必选
          abilityName: 'SecondApplicationAbility',
          parameters: {
            // 自定义信息
            info: '来自EntryAbility Page_UIAbilityComponentsInteractive页面'
          },
        }
        // context为调用方UIAbility的UIAbilityContext
        this.context.startAbility(wantInfo)
          .then(() => {
            console.log('startAbility success.');
          })
          .catch((error: BusinessError) => {
            console.log('startAbility failed.');
          });
      })
  }
}

TIP

启动其他应用的 UIAbility 可以参考-传送门

编辑

启动界面和预期不同;如何排查:

  1. 确认启动的模块
  2. 找到模块的 module.json5
  3. 找到默认启动的 Ability
  4. 打开 Ability 看看默认加载的页面
    1. 页面对不对
    2. 是否左侧有/

编辑

  1. bundleName:应用的包名,AppScore/app.json5
  2. moduleName: 模块名
    1. (同一个模块跳转,可以省略)
    2. 跳转到其他的模块,模块/module.json5
  1. abilityName:
    1. 模块/module.json5,找到 Ability 数组,确认要跳转的 Ability

​ ​

 HarmonyOS赋能资源丰富度建设(第四期)-吴东林

developer.huawei.com/consumer/cn…