HarmonyOS7 广告关闭为什么不是简单隐藏?remove 和 rebuild 要一起看


项目源码地址: https://gitcode.com/HarmonyOS_Samples/DynamicComponent

广告显示出来只是第一步。

A hand-drawn doodle illustration on pure white pap

这个项目更值得学的是:点击关闭后,广告怎么从动态节点树上下去。它不是简单改个 Visibility.Hidden,而是回到 NodeController 里控制节点返回值。

这篇拆 CloseAdDialognodeMapremove()rebuild()

关闭按钮先打开确认弹窗

广告右上角的关闭按钮在 upperText() 里:

Stack() {
  Circle()
    .height($r('app.string.close_icon_size'))
    .width($r('app.string.close_icon_size'))

  Text($r('app.string.close_icon_symbol'))
}
.onClick(() => {
  closeAdDialogController.open();
})

点击关闭按钮,不会立刻移除广告,而是打开确认弹窗。

效果是这样:

在这里插入图片描述

这个逻辑很像真实广告业务:用户点关闭,先确认是不是要屏蔽。

CustomDialogController 怎么创建

AdComponent 里,有这样一段:

closeAdDialogController: CustomDialogController = new CustomDialogController({
  builder: CloseAdDialog({
    adId: this.params!.id
  }),
  backgroundBlurStyle: BlurStyle.COMPONENT_THICK,
});

这里创建了一个弹窗控制器。

重点是 CloseAdDialog 收到了 adId。这个 adId 后面会用来找到对应广告的 AdNodeController

没有这个 id,弹窗不知道自己要关闭哪一个广告。

弹窗里的取消按钮很普通

取消按钮只关闭弹窗:

Button($r('app.string.text_dialog_cancel'))
  .onClick(() => {
    this.dialogController.close();
  })

这没什么复杂的。

真正关键的是“屏蔽”按钮。

屏蔽按钮会找回 AdNodeController

屏蔽按钮代码如下:

Button($r('app.string.text_dialog_shield'))
  .onClick(() => {
    let node: AdNodeController | undefined = nodeMap.get(this.adId);
    if (node !== undefined) {
      node.remove();
      node.rebuild();
    }
    this.dialogController.close();
  })

这段代码非常重要。

它做了三件事:

  1. 通过 adIdnodeMap 找到广告 Controller
  2. 调用 node.remove() 标记广告要移除
  3. 调用 node.rebuild() 让容器重新获取节点

最后关闭弹窗。

remove 只是改标记

AdController.ets 里的 remove() 很短:

remove() {
  this.isRemove = true;
}

它只是把 isRemove 改成 true

注意,只调用 remove() 不代表 UI 一定马上消失。它只是告诉 Controller:下次 makeNode() 被调用时,不要再返回广告节点。

makeNode 根据 isRemove 返回 null

再看 makeNode()

A hand-drawn doodle illustration on pure white pap

makeNode(): FrameNode | null {
  if (this.isRemove) {
    return null;
  }
  if (this.rootNode != null) {
    return this.rootNode;
  }
  return null;
}

isRemovetruemakeNode() 返回 null

NodeContainer 拿不到 FrameNode,广告自然就下树了。

这就是动态节点关闭的核心。

rebuild 负责重新触发 makeNode

为什么还要调用:

node.rebuild();

因为你改了 isRemove,但 NodeContainer 不一定马上知道。

rebuild() 的作用就是通知框架:这个 Controller 的节点状态变了,请重新调用 makeNode()

于是流程变成:

点击屏蔽
remove() 把 isRemove 改成 true
rebuild() 触发 makeNode()
makeNode() 发现 isRemove 为 true
返回 null
NodeContainer 不再显示广告

这比直接隐藏更符合动态节点的设计。

为什么不用 Visibility.Hidden

如果只是普通组件,当然可以用:

.visibility(Visibility.Hidden)

但这里广告是动态创建出来的节点,而且可能包含视频。

如果只是隐藏,节点还在,资源也可能还在。对于广告这种可以被彻底关闭的模块,让 makeNode() 返回 null 更干净。

小白可以先记住:普通 UI 隐藏用状态,动态节点移除用 Controller。

这个设计有什么业务价值

真实广告系统里,关闭广告往往不只是 UI 消失,还可能要做:

  • 上报关闭事件
  • 记录用户不感兴趣
  • 停止视频播放
  • 清理广告节点
  • 避免当前页面再次展示同一个广告

这些逻辑都放到 Controller 这条线上,比散落在页面里更好维护。

收个尾

这篇把广告关闭完整串起来了。

最关键的一句话是:remove() 只是改状态,rebuild() 才会让 NodeContainer 重新调用 makeNode(),而 makeNode() 返回 null 后,广告才真正下树。

下一篇我们看一个容易被忽略的细节:普通卡片 CardComponent 是怎么配合列表流工作的。动态广告不是孤立存在的,它必须和普通内容一起稳定滚动。

内容概要:本文介绍了一项创新性未发表的研究,即利用多元宇宙优化算法(Multiverse Optimizer, MVO)对分时电价下的需求响应与综合能源系统调度问题进行建模与求解,旨在实现能源系统的经济性、高效性与可持续性运行。该研究构建了包含多种能源设备(如光伏、风机、燃气轮机、储能系统等)及可调节负荷的综合能源系统模型,充分考虑了用户侧的需求响应行为在分时电价机制下的响应特性,通过MVO算法对系统运行成本、能源利用率、碳排放等多目标进行协同优化,实现了日前调度计划的智能决策。研究还提供了完整的MATLAB代码实现,便于研究人员复现实验、验证算法性能,并为进一步研究提供可靠的仿真基础。; 适合人群:具备一定电力系统、优化算法及MATLAB编程基础的科研人员、研究生以及从事能源互联网、综合能源系统规划与运行的技术工程师。; 使用场景及目标:① 学习并掌握多元宇宙优化算法在复杂能源系统调度中的具体应用方法;② 研究分时电价机制如何通过需求响应引导用户参与电网互动,实现削峰填谷;③ 实现综合能源系统(IES)中冷、热、电、气等多种能源的协同优化调度,以降低运行成本、提高新能源消纳能力系统可靠性;④ 为相关领域的学术研究提供可复现的代码实例仿真平台。; 阅读建议:此资源以MATLAB代码为核心载体,深入剖析了算法应用与系统建模的全过程。建议读者在学习时,不仅应关注代码的实现细节,更要理解其背后的数学模型、优化目标设定约束条件的物理意义。建议结合文档中的模型描述,逐步调试代码,观察不同参数场景下的优化结果,从而深刻掌握综合能源系统优化调度的设计思想与关键技术。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值