概述
BuilderNode 提供能够挂载原生组件的能力,支持通过无状态的UI方法 全局@Builder 生成组件树,并通过 getFrameNode 获取组件树的根 FrameNode 节点。该节点可以通过 NodeController 直接返回,挂载在 NodeContainer 节点下,也可以在FrameNode树结构和 RenderNode 树结构嵌入声明式的组件结构,实现混合显示的能力。同时BuilderNode可以提供纹理导出的功能,导出的纹理用于在 XComponent 中进行同层渲染显示。
BuilderNode创建的ArkTS原生控件树支持与自定义节点(例如:FrameNode、RenderNode)进行关联使用,实现了原生组件与自定义节点的混合显示。对于使用自定义节点的能力进行对接的三方框架,BuilderNode为其提供了嵌入原生组件的能力。
BuilderNode提供了组件预创建的能力,能够自定义原生组件的创建开始的时间,在后续的业务中动态挂载显示。对于一些在创建初始化耗时较长的声明式组件,比如 Web 、 XComponent 等,预创建可以有效减少组件初始化的耗时。
说明
- BuilderNode只支持一个由 wrapBuilder 包装的 全局@Builder .
- 一个新建的BuildNode在 build 之后才能通过 getFrameNode 获取到一个指向根节点的FrameNode对象,否则返回null。
- 如果传入的Builder的根节点为语法节点(if/else/foreach/…),需要额外生成一个FrameNode,在节点树中的显示为“BuilderProxyNode”。
- 如果BuilderNode通过getFrameNode将节点挂载在另一个FrameNode上,或者将其作为子节点挂载在NodeContainer节点上。则节点中使用父组件的布局约束进行布局。
- 如果BuilderNode的FrameNode通过 getRenderNode 形式将自己的节点挂载在RenderNode节点上,由于其FrameNode未上树,其大小默认为0,需要通过构造函数中的 selfIdeaSize 显式指定布局约束大小,才能正常显示。
- BuilderNode的预加载并不会减少组件的创建时间。Web组件创建的时候需要在内核中加载资源,预创建不能减少Web组件的创建的时间,但是可以让内核进行预加载,减少正式使用时候内核的加载耗时。
创建BuilderNode对象
BuilderNode对象为一个模板类,需要在创建的时候指定类型。该类型需要与后续build方法中传入的 WrappedBuilder 的类型保持一致,否则会存在编译告警导致编译失败。
创建原生组件树
通过BuilderNode的build可以实现原生组件树的创建。依照传入的WrappedBuilder对象创建组件树,并持有组件树的根节点。
说明
无状态的UI方法全局@Builder最多拥有一个根节点。
创建离线节点以及原生组件树,结合FrameNode进行使用。
BuilderNode的根节点直接作为 NodeController 的 makeNode 返回值。
import { BuilderNode, FrameNode, NodeController, UIContext } from '@kit.ArkUI'
class Params {
text: string = ""
constructor(text: string) {
this.text = text;
}
}
@Builder
function buildText(params: Params) {
Column() {
Text(params.text)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 36 })
}
}
class TextNodeController extends NodeController {
private textNode: BuilderNode<[Params]> | null = null;
private message: string = "DEFAULT";
constructor(message: string) {
super();
this.message = message;
}
makeNode(context: UIContext): FrameNode | null {
this.textNode = new BuilderNode(context);
this.textNode.build(wrapBuilder<[Params]>(buildText), new Params(this.message))
return this.textNode.getFrameNode();
}
}
@Entry
@Component
struct Index {
@State message: string = "hello"
build() {
Row() {
Column() {
NodeContainer(new TextNodeController(this.message))