仙游网站建设公司,软件开发专业专科,wordpress注册失败,长沙本土网站制作公司如何使用好 ArkUI 的 Reusable#xff1f; OpenHarmony 组件复用机制 在ArkUI中#xff0c;UI显示的内容均为组件#xff0c;由框架直接提供的称为 系统组件#xff0c;由开发者定义的称为 自定义组件。
在进行 UI 界面开发时#xff0c;通常不是简单的将系统组件进行组合…如何使用好 ArkUI 的 Reusable OpenHarmony 组件复用机制 在ArkUI中UI显示的内容均为组件由框架直接提供的称为 系统组件由开发者定义的称为 自定义组件。
在进行 UI 界面开发时通常不是简单的将系统组件进行组合使用而是需要考虑代码可复用性、业务逻辑与UI分离后续版本演进等因素。因此将UI和部分业务逻辑封装成自定义组件是不可或缺的能力。
本文主要对组件复用做一些基本介绍然后对 Reusable做分析进而帮助开发者理解设置前后的效果以及我们会尝试寻找何时使用这个属性最佳进而给开发者提出参考方案。
为什么要组件复用
使用组件复用往往是解决资源短缺的问题通过节约内存节省资源简称开源节流。
开源节流是我国理财的基本原则之一。开源指开拓财政收入来源节流指尽可能减少不必要的支出或少花钱多办事。
荀子《富国》荀子在《富国》篇中说“故田野县鄙者财之本也垣窌仓廪者财之末也百姓时和事业得叙者货币之源也等赋府库者货之流也。故明君必养其和、节其流、开其源而时斟酌焉。”其意系指农业是创造财富的根本大业聚财只是其结果货币只是流通的手段财政收入只能从流通中取得故用扩大流通的方式来增加收入对增加财富并无好处。
同理鸿蒙系统的内存是非常宝贵的它不仅需要提供给底层系统维持系统正常运行还要分配给网络、通知、后台任务、传感器、中断等一系列工作。那么我们在应用开发时就要想办法节约内存为系统工作分忧。
Reusable组件复用装饰器
在 ArkUI中使用 Component装饰器修饰组件组件允许开发者组合使用系统组件、及其属性和方法并通过状态变量的改变来驱动UI的刷新。 Reusable是修饰组件的属性赋予组件重用的特性。
什么是Reusable
Reusable 是一个装饰器它可以标识自定义组件具备可复用的能力也可以被添加到任意的自定义组件上。并且也可以在跨平台提供响应的能力。整体来说它是 ArkUI的一部分。
它的定义如下
/*** Defining Reusable ClassDecorator.** syscap SystemCapability.ArkUI.ArkUI.Full* crossplatform* since 10*/
declare const Reusable: ClassDecorator;可以看出Reusable 实际上是一个 ClassDecorator , 那么它的内部结构是如何的呢 从上图可以分析并查看 component构造函数 constructor(parent, localStorage, elmtId -1) {super();...this.recycleManager undefined;...
}从 component的构造函数中我们发现每一个 component持有一个 recycleManagerrecycleManager参与管理 Reusable 组件那么 recycleManager是如何管理复用组建的呢 接下来我们再看它的后端实现逻辑
视图层的关系如下
视图层是通过js实现的
xxxxxx
…todo
我们在视图树的结构中发现一个环众所周知环会产生内存泄漏所以在页面退出时需要将 RecycleManager中持有的view全部手动释放以此来破环。
当组件被重用时就会触发 aboutToReuse 方法
aboutToReuse?(params: { [key: string]: unknown }): void;
在这个函数中就可以重载数据。
连接层的关系如下
连接层是桥接 js 和 c的中间层。
我们在 js_ace_page.h文件中发现以下代码可以验证持有关系。
namespace OHOS::Ace::Framework {...
private:
#ifndef NG_BUILDvoid SwapBackgroundDecoration(const RefPtrPageTransitionComponent transition);
#endif...RefPtrComponent component_;
...
}节点层的关系如下
节点层是通过c实现的。
xxxxxx
…todo
那么我们接下来看下组件复用发生和不发生时的区别
组件复用发生时
在复用组件在view显示后组织结构如下 在c 构造树中当Reusable修饰的组建复用后JSView强持有c的viewpage的实例被RecycleManager 管理持有。
此时如果page被回收由于 c的view 被jsview强持有就无法得到释放。所以需要在c的析构中对RecycleManager中所有的 复用组件释放完成手动释放。
组件复用不发生时
在复用组件从view移除后组织结构发生如下变化 在c 构造树中当Reusable修饰的组建删除后JSView不再强持有c的view此时c的view被RecycleManager 管理持有等待下一次被重用。
此时如果page被回收由于 c的view 并没有被jsview强持有就可以得到释放。
。。todo
实战Reusable 可以解决的问题
现在我们知道了 Reusable 的基本功能那么它在实际开发中可以解决什么问题呢根据我的思考️和整理主要可以解决以下三类问题。
问题一解决组件嵌套过深
子组件通过Prop接收父组件传递的数据如果嵌套的层数过多会导致深拷贝占用的空间过大以及GarbageCollection(垃圾回收)引起性能问题。通过 Reusable可解决嵌套的层数过多的问题。
那么 Reusable是如何解决这个问题的请看下文
我们在开发时往往会遇到多层组件嵌套的场景通俗说就是view中套子view子view中又套孙子view以此类推。 这样就会产生一个嵌套过深的问题参考见下图 具体代码如下
Entry
Component
struct FatherView {State vote: ClassE new ClassE()build() {Column() {Button(change).onClick(() {this.vote.name Im Father})Child({ voteOne: this.vote })}}
}Component
struct SonView {Prop voteOne: ClassEbuild() {Column() {Button(change).onClick(() {this.vote.name Iam Son})Child({ voteTwo: this.vote })}}
}Component
struct SonView {Prop voteTwo: ClassDbuild() {Column() {Button(change).onClick(() {this.vote.name Iam grandson})Child({ voteThree: this.vote })}}
}...在不断增加层次后问题产生了 由于层次过深代码难以阅读并且传递关系过于复杂传递依赖链过长不满足第三范式。 第三范式表中每一列的属性都不可再分且非主属性完全依赖于主属性且每个非主属性都不传递函数依赖于主属性。 https://en.wikipedia.org/wiki/Third_normal_form 可能触发GarbageCollection(垃圾回收机制)产生问题。
具体什么条件会触发暂无资料还需要相关子系统提供源码分析。
那么在使用 Reusable优化后的效果如下 具体代码如下
Entry
Component
struct FatherView {State vote: ClassE new ClassE()build() {Column() {Button(change).onClick(() {this.vote.name Im Father})Child({ voteOne: this.vote })}}
}Reusable
Component
struct SonView {Prop voteOne: ClassEbuild() {Column() {Button(change).onClick(() {this.vote.name Iam Son})Child({ voteTwo: this.vote })}}
}Reusable
Component
struct SonView {Prop voteTwo: ClassDbuild() {Column() {Button(change).onClick(() {this.vote.name Iam grandson})Child({ voteThree: this.vote })}}
}...在使用 Reusable优化后问题解决了 消除了传递依赖代码层次结构更清晰了对于组件间互相交互也更好处理在深拷贝的传递链上已满足第三范式。 深度只有2层100%避免了由于深度增加触发GarbageCollection(垃圾回收机制)的条件避免产生问题。
问题二减少创建控件时间
。。todo
问题三使代码更优雅
。。todo
总结
。。todo
个人观点
。。todo
相关扩展
。。todo
– 缓冲池机制
传统的 LRU
什么是预读失败
什么是缓冲池污染