1. UIAbility组件生命周期
UIAbility的生命周期包括Create、Foreground、Background、Destroy四个状态。
UIAbility生命周期状态
1.1 Create状态
Create状态为在应用加载过程中,UIAbility实例创建完成时触发,系统会调用onCreate()回调。可以在该回调中进行页面初始化操作,例如变量定义资源加载等,用于后续的UI界面展示。
import UIAbility from '@ohos.app.ability.UIAbility';
import Window from '@ohos.window';
export default class EntryAbility extends UIAbility {
onCreate(want, launchParam) {
// 页面初始化
}
// ...
}
1.2 WindowStageCreate和WindowStageDestroy状态
UIAbility实例创建完成之后,在进入Foreground之前,系统会创建一个WindowStage。WindowStage创建完成后会进入onWindowStageCreate()回调,可以在该回调中设置UI界面加载、设置WindowStage的事件订阅。
在onWindowStageCreate()回调中通过loadContent()方法设置应用要加载的页面并根据需要订阅WindowStage的事件(获焦/失焦、可见/不可见)。
import UIAbility from '@ohos.app.ability.UIAbility';
import Window from '@ohos.window';
export default class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage: Window.WindowStage) {
// 设置WindowStage的事件订阅(获焦/失焦、可见/不可见)
// 设置UI界面加载
windowStage.loadContent('pages/Index', (err, data) => {
// ...
});
}
}
在UIAbility实例销毁之前会进入onWindowStageDestroy()回调,可以释放UI界面资源。
import UIAbility from '@ohos.app.ability.UIAbility';
import Window from '@ohos.window';
export default class EntryAbility extends UIAbility {
// ...
onWindowStageDestroy() {
// 释放UI界面资源
}
}
- onCreate:在 Ability 创建时被调用,用于执行初始化和设置业务逻辑。
- onDestroy:在 Ability 销毁时触发,用于执行资源清理和其他清理操作。
- onWindowStageCreate:在 WindowStage 创建完成后触发。
- onWindowStageDestroy:在 WindowStage 销毁后触发。
- onForeground:Ability 的生命周期回调,当应用从后台切换到前台时调用。
- onBackground:Ability 的生命周期回调,当应用从前台切换到后台时调用。
2. 页面和自定义组件生命周期
2.1 页面生命周期
即被@Entry装饰的组件生命周期,提供以下生命周期接口:
- onPageShow:页面每次显示时触发一次,包括路由过程、应用进入前台等场景。
- onPageHide:页面每次隐藏时触发一次,包括路由过程、应用进入后台等场景。
- onBackPress:当用户点击返回按钮时触发。
2.2 组件生命周期
即一般用@Component装饰的自定义组件的生命周期,提供以下生命周期接口:
- aboutToAppear:组件即将出现时回调该接口,具体时机为在创建自定义组件的新实例后,在执行其build()函数之前执行。
- aboutToDisappear:在自定义组件析构销毁之前执行。不允许在aboutToDisappear函数中改变状态变量,特别是@Link变量的修改可能会导致应用程序行为不稳定。
2.3 生命周期流程
下图展示的是被@Entry装饰的组件(页面)生命周期。
2.4 自定义组件的渲染流程
- ArkUI框架创建自定义组件
- 初始化自定义组件的成员变量
- 执行aboutToAppear方法
- 执行build方法渲染组件,在首次渲染时,框架会记录状态变量和组件的映射关系
- 当状态变量的值更改时,框架根据映射关系,执行这些UI组件的更新函数
- if分支或者ForEach渲染的数组个数改变,组件将被删除,在删除前执行aboutToDisappear
不建议在aboutToDisappear内使用async await,如果在aboutToDisappear使用中Promise或者回调方法,自定义组件将被保留在Promise的闭包中,直到回调方法被执行完,这个行为阻止了自定义组件的垃圾回收。
2.5 示例
import router from '@ohos.router'
@Entry
@Component
struct Index {
@State showChild: boolean = true;
// 页面生命周期
onPageShow() {
console.info('Index onPageShow');
}
// 页面生命周期
onPageHide() {
console.info('Index onPageHide');
}
// 页面生命周期
onBackPress() {
console.info('Index onBackPress');
}
// 组件生命周期
aboutToAppear() {
console.info('Index aboutToAppear');
}
// 组件生命周期
aboutToDisappear() {
console.info('Index aboutToDisappear');
}
build() {
Column() {
// this.showChild为true,创建Child子组件,执行Child aboutToAppear
if (this.showChild) {
Child()
}
// this.showChild为false,删除Child子组件,执行Child aboutToDisappear
Button('删除子组件 Child')
.margin({ bottom: 20 })
.onClick(() => {
this.showChild = false;
})
// push到DetailPage页面,执行onPageHide
Button('跳转到 DetailPage')
.onClick(() => {
router.pushUrl({ url: 'pages/DetailPage' });
})
}
.width("100%")
.height("100%")
}
}
@Component
struct Child {
@State title: string = 'Child';
// 组件生命周期
aboutToAppear() {
console.info('Child aboutToAppear')
}
// 组件生命周期
aboutToDisappear() {
console.info('Child aboutToDisappear')
}
build() {
Text(this.title).fontSize(50).onClick(() => {
this.title = 'Child Click';
})
}
}
3. 同模块下的UIAbility跳转
3.1 创建 PaymentPage
@Entry
@Component
struct PaymentPage {
@State message: string = 'payment page'
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
}
.width('100%')
}
.height('100%')
}
}
3.2 创建 PaymentAbility
修改 windowStage.loadContent 加载的页面
3.3 修改 Index.ets
import common from '@ohos.app.ability.common'
import Want from '@ohos.app.ability.Want'
@Entry
@Component
struct Index {
@State message: string = 'index page'
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
Button("去支付")
.width('100%')
.onClick(() => {
const context = getContext(this) as common.UIAbilityContext;
const want: Want = {
'deviceId': '', // deviceId为空表示本设备
'bundleName': 'com.example.myapplication',
'abilityName': 'PaymentAbility',
'moduleName': 'entry'
}
context.startAbility(want)
})
}
.width('100%')
}
.height('100%')
}
}
4. 不同模块下的UIAbility跳转
4.1 创建模块
4.2 修改 paymentModule 模块的 Index.ets
@Entry
@Component
struct Index {
@State message: string = 'payment module page'
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
}
.width('100%')
}
.height('100%')
}
}
4.3 修改 entry 模块的 Index.ets
修改 abilityName 和 moduleName
import common from '@ohos.app.ability.common'
import Want from '@ohos.app.ability.Want'
@Entry
@Component
struct Index {
@State message: string = 'index page'
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
Button("去支付")
.width('100%')
.onClick(() => {
const context = getContext(this) as common.UIAbilityContext;
const want: Want = {
'deviceId': '', // deviceId为空表示本设备
'bundleName': 'com.example.myapplication',
'abilityName': 'PaymentModuleAbility',
'moduleName': 'paymentModule'
}
context.startAbility(want)
})
}
.width('100%')
}
.height('100%')
}
}
4.4 配置调起2个模块
4.5 两个模块之间传递数据
4.5.1 修改 entry 模块的 Index.ets
使用 parameters 选项添加自定义数据
使用 context.startAbilityForResult 方法启动 UIAbility 并获取返回结果
import common from '@ohos.app.ability.common'
import Want from '@ohos.app.ability.Want'
type PaymentAbilityParams = Record<string, boolean>
@Entry
@Component
struct Index {
@State message: string = 'index page'
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
Button("去支付")
.width('100%')
.onClick(async () => {
const context = getContext(this) as common.UIAbilityContext;
const want: Want = {
deviceId: '', // deviceId为空表示本设备
bundleName: 'com.example.myapplication',
abilityName: 'PaymentModuleAbility',
moduleName: 'paymentModule',
parameters: {
orderId: Date.now()
}
}
// context.startAbility(want)
const paymentAbilityResult = await context.startAbilityForResult(want)
const params = paymentAbilityResult.want?.parameters as PaymentAbilityParams
if (params?.isPay) {
AlertDialog.show({
message: "支付成功"
})
} else {
AlertDialog.show({
message: "支付失败"
})
}
})
}
.width('100%')
}
.height('100%')
}
}
4.5.2 修改 paymentModule 模块的 PaymentModuleAbility
在 UIAbility 的 onCreate 中接收参数,并保存到 AppStorage 中
import UIAbility from '@ohos.app.ability.UIAbility';
import hilog from '@ohos.hilog';
import window from '@ohos.window';
type AbilityParams = Record<string, number>
export default class PaymentModuleAbility extends UIAbility {
onCreate(want, launchParam) {
const params = want.parameters as AbilityParams;
AppStorage.SetOrCreate<number>("orderId", params.orderId);
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
}
onDestroy() {
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
}
onWindowStageCreate(windowStage: window.WindowStage) {
// Main window is created, set main page for this ability
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
windowStage.loadContent('pages/Index', (err, data) => {
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. Data: %{public}s', JSON.stringify(data) ?? '');
});
}
onWindowStageDestroy() {
// Main window is destroyed, release UI related resources
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
}
onForeground() {
// Ability has brought to foreground
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
}
onBackground() {
// Ability has back to background
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
}
}
4.5.3 修改 paymentModule 模块的 Index.ets
从 storage 中获取 orderId
点击支付按钮, PaymentModuleAbility 停止自身并返回结果
import common from '@ohos.app.ability.common'
@Entry
@Component
struct Index {
@State message: string = 'payment module page'
@StorageProp("orderId") orderId: number = 0
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
Text(`${this.orderId}`)
.fontSize(50)
.fontColor(Color.Red)
Button("支付").onClick(() => {
const context = getContext(this) as common.UIAbilityContext;
context.terminateSelfWithResult({
resultCode: 1,
want: {
deviceId: '', // deviceId为空表示本设备
bundleName: 'com.example.myapplications',
abilityName: 'EntryAbility',
moduleName: 'entry',
parameters: {
isPay: true
}
}
})
})
}
.width('100%')
}
.height('100%')
}
}