HarmonyOS使用WrapBuilder包裹自定义Component,自定义Component中复写的aboutToDsiappear回调不会被执行?

一个自定义Component,复写了aboutToDsiappear方法,

  1. 当把该Component直接添加到view tree,页面退出aboutToDsiappear能正常执行
  2. 使用WrapBuilder包裹自定义Component,页面退出自定义Component中复写的aboutToDsiappear回调不会被执行;

复现代码:

import { UIContext } from '@ohos.arkui.UIContext';
import { NodeController, BuilderNode, FrameNode } from '@ohos.arkui.node';

class Params {
  text: string = "this is a text"
}


@Component
export struct MyComponent {
  aboutToAppear(): void {
    console.log("about to appear");
  }

  aboutToDisappear(): void {
    //// BUG: 放在WrapBuilder里,这个回调不会被执行!
    console.log("about to disappear");
  }

  build() {
    TextInput({placeholder:'hhh'})
      .width('70%')
      .height(48)
      .fontSize(14)
      .fontColor(Color.Black)
  }
}

@Builder
function MyBuilder(params: Params) {
  Column() {
    MyComponent()
      .onDetach(()=>{
        console.log("onDetach called");
      })
      .onDisAppear(()=>{
        console.log("on disappear called");
      })
  }
  .width('100%')
  .height(300)
  // .backgroundColor(Color.Gray)
}

class MyNodeController extends NodeController {
  private rootNode: BuilderNode<[Params]> | null = null;
  private wrapBuilder: WrappedBuilder<[Params]> = wrapBuilder(MyBuilder);

  makeNode(uiContext: UIContext): FrameNode | null {
    this.rootNode = new BuilderNode(uiContext);
    this.rootNode.build(this.wrapBuilder, { text: "this is a string" })
    return this.rootNode.getFrameNode();
  }

  postTouchEvent(touchEvent: TouchEvent): void {
    if(this.rootNode == null){
      return;
    }
    let result = this.rootNode.postTouchEvent(touchEvent);
    console.log("result " + result);
  }
}

@Entry
@Component
struct Index {
  private nodeController: MyNodeController = new MyNodeController();

  build() {
    Stack() {
      /// 使用NodeContainer + WrapBuilder里 , MyComponent#AboutToDisappear不会被执行
      NodeContainer(this.nodeController)
        .height(300)
        .width('100%')

      /// 直接写 Component , AboutToDisappear 会被执行
      // MyComponent()
    }
  }
}
阅读 467
1 个回答

通过释放BuilderNode对象来触发自定义组件的析构,依赖于虚拟机的gc,即无法立刻触发自定组件的aboutToDisappear回调。

需要应用主动去dispose,demo如下

import { BuilderNode } from '@kit.ArkUI';

class MyNodeController extends NodeController {
  private rootNode: BuilderNode<[Params]> | null = null;
  private wrapBuilder: WrappedBuilder<[Params]> = wrapBuilder(MyBuilder);

  makeNode(uiContext: UIContext): FrameNode | null {
    this.rootNode = new BuilderNode(uiContext);
    this.rootNode.build(this.wrapBuilder, { text: "this is a string" })
    return this.rootNode.getFrameNode();
  }

  dispose() {
    this.rootNode?.dispose();
  }

  postTouchEvent(touchEvent: TouchEvent): void {
    if (this.rootNode == null) {
      return;
    }
    let result = this.rootNode.postTouchEvent(touchEvent);
    console.log("result " + result);
  }
}

@Entry
@Component
struct Index {
  private nodeController: MyNodeController = new MyNodeController();

  onBackPress(): boolean | void {
    // 销毁节点
    this.nodeController.dispose();
  }

  build() {
    Stack() {
      /// 使用NodeContainer + WrapBuilder里 , MyComponent#AboutToDisappear不会被执行
      NodeContainer(this.nodeController)
        .height(300)
        .width('100%')

      /// 直接写 Component , AboutToDisappear 会被执行
      // MyComponent()
    }
  }
}