• OpenHarmony自定义组件的生命周期


    自定义组件的创建和渲染流程

    1. 自定义组件的创建:自定义组件的实例由ArkUI框架创建。

    2. 初始化自定义组件的成员变量:通过本地默认值或者构造方法传递参数来初始化自定义组件的成员变量,初始化顺序为成员变量的定义顺序。

    3. 如果开发者定义了aboutToAppear,则执行aboutToAppear方法。

    4. 在首次渲染的时候,执行build方法渲染系统组件,如果子组件为自定义组件,则创建自定义组件的实例。在执行build()函数的过程中,框架会观察每个状态变量的读取状态,将保存两个map:

      1. 状态变量 -> UI组件(包括ForEach和if)。
      2. UI组件 -> 此组件的更新函数,即一个lambda方法,作为build()函数的子集,创建对应的UI组件并执行其属性方法,示意如下。
      1. build() {
      2. ...
      3. this.observeComponentCreation(() => {
      4. Button.create();
      5. })
      6. this.observeComponentCreation(() => {
      7. Text.create();
      8. })
      9. ...
      10. }

      当应用在后台启动时,此时应用进程并没有销毁,所以仅需要执行onPageShow。

    自定义组件重新渲染

    当事件句柄被触发(比如设置了点击事件,即触发点击事件)改变了状态变量时,或者LocalStorage / AppStorage中的属性更改,并导致绑定的状态变量更改其值时:

    1. 框架观察到了变化,将启动重新渲染。

    2. 根据框架持有的两个map(自定义组件的创建和渲染流程中第4步),框架可以知道该状态变量管理了哪些UI组件,以及这些UI组件对应的更新函数。执行这些UI组件的更新函数,实现最小化更新。

    自定义组件的删除

    如果if组件的分支改变,或者ForEach循环渲染中数组的个数改变,组件将被删除:

    1. 在删除组件之前,将调用其aboutToDisappear生命周期函数,标记着该节点将要被销毁。ArkUI的节点删除机制是:后端节点直接从组件树上摘下,后端节点被销毁,对前端节点解引用,当前端节点已经没有引用时,将被JS虚拟机垃圾回收。

    2. 自定义组件和它的变量将被删除,如果其有同步的变量,比如@Link@Prop@StorageLink,将从同步源上取消注册。

    不建议在生命周期aboutToDisappear内使用async await,如果在生命周期的aboutToDisappear使用异步操作(Promise或者回调方法),自定义组件将被保留在Promise的闭包中,直到回调方法被执行完,这个行为阻止了自定义组件的垃圾回收。

    以下示例展示了生命周期的调用时机:

    1. // Index.ets
    2. import router from '@ohos.router';
    3. @Entry
    4. @Component
    5. struct MyComponent {
    6. @State showChild: boolean = true;
    7. // 只有被@Entry装饰的组件才可以调用页面的生命周期
    8. onPageShow() {
    9. console.info('Index onPageShow');
    10. }
    11. // 只有被@Entry装饰的组件才可以调用页面的生命周期
    12. onPageHide() {
    13. console.info('Index onPageHide');
    14. }
    15. // 只有被@Entry装饰的组件才可以调用页面的生命周期
    16. onBackPress() {
    17. console.info('Index onBackPress');
    18. }
    19. // 组件生命周期
    20. aboutToAppear() {
    21. console.info('MyComponent aboutToAppear');
    22. }
    23. // 组件生命周期
    24. aboutToDisappear() {
    25. console.info('MyComponent aboutToDisappear');
    26. }
    27. build() {
    28. Column() {
    29. // this.showChild为true,创建Child子组件,执行Child aboutToAppear
    30. if (this.showChild) {
    31. Child()
    32. }
    33. // this.showChild为false,删除Child子组件,执行Child aboutToDisappear
    34. Button('delete Child').onClick(() => {
    35. this.showChild = false;
    36. })
    37. // push到Page2页面,执行onPageHide
    38. Button('push to next page')
    39. .onClick(() => {
    40. router.pushUrl({ url: 'pages/Page2' });
    41. })
    42. }
    43. }
    44. }
    45. @Component
    46. struct Child {
    47. @State title: string = 'Hello World';
    48. // 组件生命周期
    49. aboutToDisappear() {
    50. console.info('[lifeCycle] Child aboutToDisappear')
    51. }
    52. // 组件生命周期
    53. aboutToAppear() {
    54. console.info('[lifeCycle] Child aboutToAppear')
    55. }
    56. build() {
    57. Text(this.title).fontSize(50).onClick(() => {
    58. this.title = 'Hello ArkUI';
    59. })
    60. }
    61. }

    以上示例中,Index页面包含两个自定义组件,一个是被@Entry装饰的MyComponent,也是页面的入口组件,即页面的根节点;一个是Child,是MyComponent的子组件。只有@Entry装饰的节点才可以生效页面的生命周期方法,所以MyComponent中声明了当前Index页面的页面生命周期函数。MyComponent和其子组件Child也同时声明了组件的生命周期函数。

    • 应用冷启动的初始化流程为:MyComponent aboutToAppear --> MyComponent build --> Child aboutToAppear --> Child build --> Child build执行完毕 --> MyComponent build执行完毕 --> Index onPageShow。

    • 点击“delete Child”,if绑定的this.showChild变成false,删除Child组件,会执行Child aboutToDisappear方法。

    • 点击“push to next page”,调用router.pushUrl接口,跳转到另外一个页面,当前Index页面隐藏,执行页面生命周期Index onPageHide。此处调用的是router.pushUrl接口,Index页面被隐藏,并没有销毁,所以只调用onPageHide。跳转到新页面后,执行初始化新页面的生命周期的流程。

    • 如果调用的是router.replaceUrl,则当前Index页面被销毁,执行的生命周期流程将变为:Index onPageHide --> MyComponent aboutToDisappear --> Child aboutToDisappear。上文已经提到,组件的销毁是从组件树上直接摘下子树,所以先调用父组件的aboutToDisappear,再调用子组件的aboutToDisAppear,然后执行初始化新页面的生命周期流程。

    • 点击返回按钮,触发页面生命周期Index onBackPress,且触发返回一个页面后会导致当前Index页面被销毁。

    • 最小化应用或者应用进入后台,触发Index onPageHide。当前Index页面没有被销毁,所以并不会执行组件的aboutToDisappear。应用回到前台,执行Index onPageShow。

    • 退出应用,执行Index onPageHide --> MyComponent aboutToDisappear --> Child aboutToDisappear。

  • 相关阅读:
    【Page-level Heap Fengshui -- Cross-Cache Overflow】corCTF2022-cache-of-castaways
    Ansible 2.6 Pthon API
    excel的时间和日期的获取
    P1827 [USACO3.4] 美国血统 American Heritage(前序 + 中序 生成后序)
    设计模式- 适配器模式(Adapter Pattern)结构|原理|优缺点|场景|示例
    分类预测 | MATLAB实现GRU门控循环单元多特征分类预测
    java计算机毕业设计人才库构建研究源码+数据库+lw文档+系统
    【web-解析目标】(1.2.4)解析应用程序:解析受攻击面
    Andorid项目源码(167套)
    A. Image
  • 原文地址:https://blog.csdn.net/liuhaikang/article/details/133851612