鸿蒙系列-如何使用好 ArkUI 的 @Reusable?

这篇具有很好参考价值的文章主要介绍了鸿蒙系列-如何使用好 ArkUI 的 @Reusable?。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

如何使用好 ArkUI 的 @Reusable?

OpenHarmony 组件复用机制

在ArkUI中,UI显示的内容均为组件,由框架直接提供的称为 系统组件,由开发者定义的称为 自定义组件

在进行 UI 界面开发时,通常不是简单的将系统组件进行组合使用,而是需要考虑代码可复用性、业务逻辑与UI分离,后续版本演进等因素。因此,将UI和部分业务逻辑封装成自定义组件是不可或缺的能力。

本文主要对组件复用做一些基本介绍,然后对 @Reusable做分析,进而帮助开发者理解设置前后的效果,以及我们会尝试寻找何时使用这个属性最佳,进而给开发者提出参考方案。

为什么要组件复用?

使用组件复用往往是解决资源短缺的问题,通过节约内存节省资源,简称开源节流。

开源节流是我国理财的基本原则之一。开源指开拓财政收入来源,节流指尽可能减少不必要的支出,或少花钱多办事。

荀子 《富国》
鸿蒙系列-如何使用好 ArkUI 的 @Reusable?,鸿蒙应用,arkui开发,open harmony开发,ios,oh,openharmony,arkui 荀子在《富国》篇中说“故田野县鄙者,财之本也;垣窌仓廪者,财之末也;百姓时和,事业得叙者,货币之源也;等赋府库者,货之流也。故明君必养其和、节其流、开其源而时斟酌焉。”其意系指农业是创造财富的根本大业,聚财只是其结果,货币只是流通的手段,财政收入只能从流通中取得,故用扩大流通的方式来增加收入,对增加财富并无好处。

同理,鸿蒙系统的内存是非常宝贵的,它不仅需要提供给底层系统维持系统正常运行,还要分配给网络、通知、后台任务、传感器、中断等一系列工作。那么我们在应用开发时就要想办法节约内存,为系统工作分忧。

@Reusable组件复用装饰器

在 ArkUI中,使用 @Component装饰器修饰组件,组件允许开发者组合使用系统组件、及其属性和方法,并通过状态变量的改变,来驱动UI的刷新。 @Reusable是修饰组件的属性,赋予组件重用的特性。
鸿蒙系列-如何使用好 ArkUI 的 @Reusable?,鸿蒙应用,arkui开发,open harmony开发,ios,oh,openharmony,arkui

什么是@Reusable?

@Reusable 是一个装饰器,它可以标识自定义组件具备可复用的能力,也可以被添加到任意的自定义组件上。并且也可以在跨平台提供响应的能力。整体来说,它是 ArkUI的一部分。

它的定义如下:

/**
 * Defining Reusable ClassDecorator.
 *
 * @syscap SystemCapability.ArkUI.ArkUI.Full
 * @crossplatform
 * @since 10
 */
declare const Reusable: ClassDecorator;

可以看出,Reusable 实际上是一个 ClassDecorator , 那么它的内部结构是如何的呢?

  • 鸿蒙系列-如何使用好 ArkUI 的 @Reusable?,鸿蒙应用,arkui开发,open harmony开发,ios,oh,openharmony,arkui

从上图可以分析并查看 component构造函数:

    constructor(parent, localStorage, elmtId = -1) {
        super();
        ...
        this.recycleManager = undefined;
        ...
}

component的构造函数中我们发现,每一个 component持有一个 recycleManagerrecycleManager参与管理 Reusable 组件,那么 recycleManager是如何管理复用组建的呢?

鸿蒙系列-如何使用好 ArkUI 的 @Reusable?,鸿蒙应用,arkui开发,open harmony开发,ios,oh,openharmony,arkui

接下来我们再看它的后端实现逻辑:

视图层的关系如下:

视图层是通过js实现的,

  1. xxx
  2. xxx

…todo

我们在视图树的结构中发现一个环,众所周知,环会产生内存泄漏,所以在页面退出时,需要将 RecycleManager中持有的view全部手动释放,以此来破环。

当组件被重用时,就会触发 aboutToReuse 方法:

aboutToReuse?(params: { [key: string]: unknown }): void;

在这个函数中就可以重载数据。

连接层的关系如下:

连接层是桥接 js 和 c++的中间层。

我们在 js_ace_page.h文件中发现以下代码,可以验证持有关系。

namespace OHOS::Ace::Framework {

...
private:
#ifndef NG_BUILD
    void SwapBackgroundDecoration(const RefPtr<PageTransitionComponent>& transition);
#endif
    ...
    RefPtr<Component> component_;
...
}
节点层的关系如下:

节点层是通过c++实现的。

  1. xxx
  2. xxx

…todo

那么我们接下来看下组件复用发生和不发生时的区别:

组件复用发生时:

在复用组件在view显示后,组织结构如下:

鸿蒙系列-如何使用好 ArkUI 的 @Reusable?,鸿蒙应用,arkui开发,open harmony开发,ios,oh,openharmony,arkui

在c++
构造树中,当@Reusable修饰的组建复用后,JSView强持有c++的view,page的实例被RecycleManager 管理持有。

此时如果page被回收,由于 c++的view 被jsview强持有,就无法得到释放。所以需要在c++的析构中,对RecycleManager中所有的 复用组件释放,完成手动释放。

组件复用不发生时:

在复用组件从view移除后,组织结构发生如下变化:

鸿蒙系列-如何使用好 ArkUI 的 @Reusable?,鸿蒙应用,arkui开发,open harmony开发,ios,oh,openharmony,arkui

在c++
构造树中,当@Reusable修饰的组建删除后,JSView不再强持有c++的view,此时c++的view被RecycleManager 管理持有,等待下一次被重用。

此时如果page被回收,由于 c++的view 并没有被jsview强持有,就可以得到释放。

。。todo文章来源地址https://www.toymoban.com/news/detail-683522.html

实战:@Reusable 可以解决的问题:

现在我们知道了 @Reusable 的基本功能,那么它在实际开发中可以解决什么问题呢?根据我的思考🤔️和整理,主要可以解决以下三类问题。

问题一:解决组件嵌套过深:

子组件通过@Prop接收父组件传递的数据,如果嵌套的层数过多,会导致深拷贝占用的空间过大以及GarbageCollection(垃圾回收),引起性能问题。通过 @Reusable可解决嵌套的层数过多的问题。

那么 @Reusable是如何解决这个问题的?请看下文:

我们在开发时往往会遇到多层组件嵌套的场景,通俗说就是view中套子view,子view中又套孙子view,以此类推。
这样就会产生一个嵌套过深的问题参考,见下图:

鸿蒙系列-如何使用好 ArkUI 的 @Reusable?,鸿蒙应用,arkui开发,open harmony开发,ios,oh,openharmony,arkui

具体代码如下:

@Entry
@Component
struct FatherView {
  @State vote: ClassE = new ClassE()

  build() {
    Column() {
      Button('change')
        .onClick(() => {
          this.vote.name = "I'm Father"
        })
      Child({ voteOne: this.vote })
    }
  }
}

@Component
struct SonView {
  @Prop voteOne: ClassE

  build() {
    Column() {
      Button('change')
        .onClick(() => {
          this.vote.name = "I'am Son"
        })
      Child({ voteTwo: this.vote })
    }
  }
}


@Component
struct SonView {
  @Prop voteTwo: ClassD

  build() {
    Column() {
      Button('change')
        .onClick(() => {
          this.vote.name = "I'am grandson"
        })
      Child({ voteThree: this.vote })
    }
  }
}

...

在不断增加层次后,问题产生了:

  1. 由于层次过深,代码难以阅读,并且传递关系过于复杂,传递依赖链过长,不满足第三范式。
    第三范式:表中每一列的属性都不可再分,且非主属性完全依赖于主属性,且每个非主属性都不传递函数依赖于主属性。 https://en.wikipedia.org/wiki/Third_normal_form

  2. 可能触发GarbageCollection(垃圾回收机制),产生问题。

具体什么条件会触发,暂无资料,还需要相关子系统提供源码分析🧐。

那么在使用 @Reusable优化后的效果如下:

鸿蒙系列-如何使用好 ArkUI 的 @Reusable?,鸿蒙应用,arkui开发,open harmony开发,ios,oh,openharmony,arkui

具体代码如下:

@Entry
@Component
struct FatherView {
  @State vote: ClassE = new ClassE()

  build() {
    Column() {
      Button('change')
        .onClick(() => {
          this.vote.name = "I'm Father"
        })
      Child({ voteOne: this.vote })
    }
  }
}

@@Reusable
@Component
struct SonView {
  @Prop voteOne: ClassE

  build() {
    Column() {
      Button('change')
        .onClick(() => {
          this.vote.name = "I'am Son"
        })
      Child({ voteTwo: this.vote })
    }
  }
}

@@Reusable
@Component
struct SonView {
  @Prop voteTwo: ClassD

  build() {
    Column() {
      Button('change')
        .onClick(() => {
          this.vote.name = "I'am grandson"
        })
      Child({ voteThree: this.vote })
    }
  }
}

...

在使用 @Reusable优化后,问题解决了:

  1. 消除了传递依赖,代码层次结构更清晰了,对于组件间互相交互也更好处理,在深拷贝的传递链上已满足第三范式。

  2. 深度只有2层,100%避免了由于深度增加触发GarbageCollection(垃圾回收机制)的条件,避免产生问题。

问题二:减少创建控件时间:

。。todo

问题三:使代码更优雅:

。。todo

总结:

。。todo

个人观点:

。。todo

相关扩展:

。。todo

– 缓冲池机制:

传统的 LRU:

什么是预读失败?

什么是缓冲池污染?

到了这里,关于鸿蒙系列-如何使用好 ArkUI 的 @Reusable?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【鸿蒙软件开发】ArkUI之容器组件Counter(计数器组件)、Flex(弹性布局)

    Counter容器组件:计数器组件,提供相应的增加或者减少的计数操作。 Flex容器组件:以弹性方式布局子组件的容器组件。 计数器组件,提供相应的增加或者减少的计数操作。 说明 该组件从API Version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本

    2024年02月06日
    浏览(46)
  • OpenHarmony 应用 ArkUI 状态管理开发范例

    本文转载自《#2023 盲盒+码 # OpenHarmony 应用 ArkUI 状态管理开发范例》,作者:zhushangyuan_ 本文根据橘子购物应用,实现 ArkUI 中的状态管理。 在声明式 UI 编程框架中,UI 是程序状态的运行结果,用户构建了一个 UI 模型,其中应用的运行时的状态是参数。当参数改变时,UI 作为

    2024年02月10日
    浏览(37)
  • 鸿蒙ArkUI实例:【自定义组件】

     组件是 OpenHarmony 页面最小显示单元,一个页面可由多个组件组合而成,也可只由一个组件组合而成,这些组件可以是ArkUI开发框架自带系统组件,比如  Text  、  Button  等,也可以是自定义组件,本节笔者简单介绍一下自定义组件的语法规范。 自定义一个组件,首先要定义

    2024年04月14日
    浏览(39)
  • 鸿蒙Harmony ArkUI十大开源项目

    一 ArkUI_Component https://gitee.com/J-Design/ArkUI_Component ArkUI组件库示例App。包括基础组件、容器组件、弹窗组件,可以在预览器或真机中,实时预览组件接口、属性调整的效果。 ArkUI 组件示例覆盖情况 继续研究更新中 组件名称 ArkUI组件示例 备注 基础组件 AlphabetIndexer - Blank - Butto

    2024年02月04日
    浏览(53)
  • 鸿蒙ArkUI即将取代Java UI?

    关注前端开发的同学,一定听过近些年,DSL 描述式的 UI 构建写法,大有取代传统命令式布局的趋势。 传统上,写一套 UI 代码,需要根据数据的逻辑,手动的在业务代码里,去改变界面 UI 元素的状态,造成业务代码和 UI 代码搅在一起,黑话=“耦合性极高”。结果就是,把人

    2024年02月11日
    浏览(43)
  • 鸿蒙ArkUI声明式学习:【UI资源管理】

    OpenHarmony 应用的资源分类和资源的访问以及应用开发使用的像素单位以及各单位之间相互转换的方法。 移动端应用开发常用到的资源比如图片,音视频,字符串等都有固定的存放目录,OpenHarmony 把这些应用的资源文件统一放在  resources  目录下的各子目录中便于开发者使用和

    2024年04月23日
    浏览(32)
  • 鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之NavDestination组件

     鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之NavDestination组件 一、操作环境 操作系统:  Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1+ 二、NavDestination组件 作为NavRouter组件的子组件,用于显示导航内容区。 子组件 可以包含子组件。 接口 NavDestination() 属性 仅支持backgroundColo

    2024年02月20日
    浏览(44)
  • 鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之NavRouter组件

    鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之NavRouter组件 一、操作环境 操作系统:  Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1+ 二、NavRouter组件 导航组件,默认提供点击响应处理,不需要开发者自定义点击事件逻辑。 子组件 必须包含两个子组件,其中第二个子组件必须为

    2024年02月21日
    浏览(42)
  • 鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Blank组件

    鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Blank组件 一、操作环境 操作系统:  Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1+ 二、Blank组件 空白填充组件,在容器主轴方向上,空白填充组件具有自动填充容器空余部分的能力。仅当父组件为Row/Column/Flex时生效。 子组件 无 接口

    2024年02月19日
    浏览(53)
  • 鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之TextInput输入框组件

    鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之TextInput输入框组件 一、操作环境 操作系统:  Windows 10 专业版 IDE:DevEco Studio 3.1 SDK:HarmonyOS 3.1 二、TextInput TextInput(value?:{placeholder?: ResourceStr, text?: ResourceStr, controller?: TextInputController}) 参数: 参数名 参数类型 必填 参数描述 placeholder Resou

    2024年02月04日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包