【鸿蒙开发】生命周期

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%')
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/550426.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

gcc常用命令指南(更新中...)

笔记为gcc常用命令指南&#xff08;自用&#xff09;&#xff0c;用到啥方法就具体研究一下&#xff0c;更新进去... 编译过程的分布执行 64位系统生成32位汇编代码 gcc -m32 test.c -o test -m32用于生成32位汇编语言

大学生前端学习第一天:了解前端

引言&#xff1a; 哈喽&#xff0c;各位大学生们&#xff0c;大家好呀&#xff0c;在本篇博客&#xff0c;我们将引入一个新的板块学习&#xff0c;那就是前端&#xff0c;关于前端&#xff0c;GPT是这样描述的&#xff1a;前端通常指的是Web开发中用户界面的部分&#xff0c;…

【读论文】【泛读】三篇生成式自动驾驶场景生成: Bevstreet, DisCoScene, BerfScene

文章目录 1. Street-View Image Generation from a Bird’s-Eye View Layout1.1 Problem introduction1.2 Why1.3 How1.4 My takeaway 2. DisCoScene: Spatially Disentangled Generative Radiance Fields for Controllable 3D-aware Scene Synthesis2.1 What2.2 Why2.3 How2.4…

解决QtCreator不能同时运行多个程序的方法

当我们运行QtCreator代码的时候&#xff0c;往往一个代码&#xff0c;可能需要打开好几个运行&#xff0c;但是会出现的情况就是&#xff0c;如果打开了一个界面&#xff0c;当我么再运行的时候&#xff0c;第一个界面就没有了&#xff0c;而且可能会出现终端报错的情况&#x…

虚拟环境下的Pip引用外部环境的解决方法

当你使用新创建的虚拟环境时&#xff0c;测试pip list却显示了一堆自己没有的功能包&#xff0c;这是因为你的环境错乱了&#xff0c;废话不多说直接上解决办法。 设置-》高级系统设置 环境变量 在系统变量部分&#xff0c;Anaconda要求前边没有其余的python环境路径。

开源全方位运维监控工具:HertzBeat

HertzBeat&#xff1a;实时监控系统性能&#xff0c;精准预警保障业务稳定- 精选真开源&#xff0c;释放新价值。 概览 HertzBeat是一款深受广大开发者喜爱的开源实时监控解决方案。它以其简洁直观的设计理念和免安装Agent的特性&#xff0c;实现了对各类服务器、数据库及应用…

vagrant 安装虚拟机,docker, k8s

第一步&#xff1a;安装虚拟机 1、安装 vagrant 本机是 mac, 但是这一步不影响&#xff0c;找对应操作系统的安装方式就行了。 vagrant 下载地址 brew install vagrant 2、下载 VirtualBox 虚拟机 VirtualBox 下载地址 找到对应系统下载&#xff0c;安装就可以。 尽量把…

项目中,如何写 readme.md 文件 | 写项目总结

tips&#xff1a;注意写 1. readme文件&#xff1a;①项目文档&#xff08;项目需求和设计文档、项目系统架构和技术文档、接口文档&#xff09;、②项目结构、③启动项目。具体结构见下文。 2. 项目总结&#xff1a;技术栈、描述、主要工作&#xff01;&#xff01;需求及功…

Rust面试宝典第4题:打家劫舍

题目 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统。如果两间相邻的房屋在同一晚上被小偷闯入&#xff0c;系统会自动报警。 给定一个代表每个房屋存放金额的非负整…

多线程传参以及线程的优缺点

进程是资源分配的基本单位 线程是调度的基本单位 笼统来说&#xff0c;线程有以下优点&#xff1a; 创建一个新线程的代价要比创建一个新进程小得多 与进程之间的切换相比&#xff0c;线程之间的切换需要操作系统做的工作要少很多 线程占用的资源要比进程少很多 能充分利用多…

Pytorch手撸Attention

Pytorch手撸Attention 注释写的很详细了&#xff0c;对照着公式比较下更好理解&#xff0c;可以参考一下知乎的文章 注意力机制 import torch import torch.nn as nn import torch.nn.functional as Fclass SelfAttention(nn.Module):def __init__(self, embed_size):super(S…

Sy-linux下常用的网络命令linux network commands

linux下的网络命令非常强大&#xff0c;这里根据教材需要&#xff0c;列出来常用的网络命令和场景实例&#xff0c;供参考。 一、命令列表&#xff1a; Command Description ip Manipulating routing to assigning and configuring network parameters traceroute Identi…

【Java】通过poi给word首页添加水印图片

背景&#xff1a; poi并没有提供直接插入水印图片的方法&#xff0c;目前需要再word的首页插入一张水印图片&#xff0c;于是就需要通过另一种方式&#xff0c;插入透明图片&#xff08;png格式&#xff09;并将图片设置为“浮于文字上方”的方式实现该需求。 所需jar&#xf…

Linux解压4GB以上zip文件

Linux使用unzip解压大于4GB文件&#xff0c;会出现以下错误&#xff1a; 解决方法 安装p7zip yum -y install p7zip执行命令&#xff1a; 7za x MSRVTT.zip

Spark-机器学习(2)特征工程之特征提取

在之前的文章中&#xff0c;我们了解我们的机器学习&#xff0c;了解我们spark机器学习中的MLIib算法库&#xff0c;知道它大概的模型&#xff0c;熟悉并认识它。想了解的朋友可以查看这篇文章。同时&#xff0c;希望我的文章能帮助到你&#xff0c;如果觉得我的文章写的不错&a…

HackMyVM-Connection

目录 信息收集 arp nmap WEB web信息收集 dirsearch smbclient put shell 提权 系统信息收集 suid gdb提权 信息收集 arp ┌─[rootparrot]─[~/HackMyVM] └──╼ #arp-scan -l Interface: enp0s3, type: EN10MB, MAC: 08:00:27:16:3d:f8, IPv4: 192.168.9.115 S…

js打印页面源码 ,打印选取的容器里的内容,打印指定内容

js打印页面源码 &#xff0c;打印选取的容器里的内容&#xff0c;打印指定内容 效果 代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge&…

FreeRTOS时间管理

FreeRTOS时间管理 主要要了解延时函数&#xff1a; 相对延时&#xff1a;指每次延时都是从执行函数vTaskDelay()开始&#xff0c;直到延时指定的时间结束。 绝对延时&#xff1a;指将整个任务的运行周期看成一个整体&#xff0c;适用于需要按照一定频率运行的任务。 函数 vTa…

PTA图论的搜索题

目录 7-1 列出连通集 题目 输入格式: 输出格式: 输入样例: 输出样例: AC代码 7-2 六度空间 题目 输入格式: 输出格式: 输入样例: 输出样例: 思路 AC代码 7-3 地下迷宫探索 题目 输入格式: 输出格式: 输入样例1: 输出样例1: 输入样例2: 输出样例2: 思路 …

MySQL 试图

视图功能在 5.0 以后的版本启用 视图是一张虚表。数据表确实包含了具体数据并且保存到硬盘中的实表。视图使用数据检索语句动态生 成的一张虚表。每一次数据服务重启或者系统重启之后&#xff0c;在数据库服务启动期间&#xff0c;会使用创建视图的语 句重新生成视图中的数据&…
最新文章