目录
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.');
});
}
注意:
- windowStage.loadContent加载的页面,不可以用 / 开头
- 加载的页面需要在 main_pages.json5 中存在
- 出现页面白色的(上述 2 个问题)
1.2 UIAbility 组件的生命周期
当用户打开、切换和返回到对应应用时,应用中的UIAbility实例会在其生命周期的不同状态之间转换。UIAbility类提供了一系列【回调函数】,如果需要在特定的时间添加自定义逻辑,往对应的回调函数内添加代码即可
tips:
- 回调函数由【开发者注册】
- 回调函数由【系统调用】,并且会传入对应的参数
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 可以通过如下方式进行设置:
- 调整配置:
-
- 配置中增加:exported 和 skills ,并移除默认Ability 中对应的配置
- 调整顺序:
-
- 如果多个 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 种情况:
- 启动同一个模块中的其他 UIAbility(目前代码的情况)
- 启动不同模块中的 UIAbility
1.3.3.1 同一个模块中的 UIAbility
同一个模块中的UIAbility跳转
这部分代码能够 C+V 并且【调整】为需要的值即可:
- 准备 want 作为 UIAbility 的启动入口参数,然后设置对应的属性值
- 通过 this.context获取当前 UIAbility 的【上下文对象】,然后调用 startAbility 并传入 want 即可实现启动
上下文对象:其提供了应用的一些【基础信息】和一些可以【调用的方法】
试一试:
- 从上一步【 添加的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 再分开,可以通过分模块的方式来实现
- 创建模块
- 调整新创建模块内部的页面内容
@Entry
@Component
struct Index {
build() {
Row() {
Column() {
Text('其他模块的页面')
.fontSize(50)
.fontWeight(FontWeight.Bold)
}
.width('100%')
}
.height('100%')
.backgroundColor('#0094ff')
}
}
现在项目中有多个模块,需要在编辑配置中将多个模块都勾选上
- 在原模块中跳转到 新创建模块中的 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 可以参考-传送门
启动界面和预期不同;如何排查:
- 确认启动的模块
- 找到模块的 module.json5
- 找到默认启动的 Ability
- 打开 Ability 看看默认加载的页面
-
- 页面对不对
- 是否左侧有/
- bundleName:应用的包名,AppScore/app.json5
- moduleName: 模块名
-
- (同一个模块跳转,可以省略)
- 跳转到其他的模块,模块/module.json5
- abilityName:
-
- 模块/module.json5,找到 Ability 数组,确认要跳转的 Ability