HarmonyOs~ArkUI进阶 之 状态管理

news2025/1/12 2:48:16

合理选择装饰器

最小化状态共享范围

在没有强烈的业务需求下,尽可能按照状态需要共享的最小范围选择合适的装饰器。

应用开发过程中,按照组件颗粒度,状态一般分为组件内独享的状态和组件间需要共享的状态

组件间需要共享的状态

组件间需要共享的状态,按照共享范围从小到大依次有三种场景:

父子组件间共享状态,不同子树上组件间共享状态和不同组件树间共享状态

  • 父子组件间共享状态:如下图,
  • ”父组件”和其子组件”子组件A”、”子组件B”共享状态loading。
  • 图3 父子组件间共享状态场景

  • 不同子树上组件间共享状态:
  • 如下图,祖先组件的左子树上”孙子组件AAA”和右子树上”孙子组件BAA”共享状态loading。
  • 图4 不同子树上组件间状态共享场景

  • 不同组件树间共享状态:
  • 如下图,组件树A内”子组件AA”和组件树B内”孙子组件AAA”共享状态loading。
  • 图5 不同组件树间共享状态的场景

对于上述三种场景,ArkUI提供了@State+@Prop、@State+@Link、@State+@Observed+@ObjectLink、@Provide+@Consume、AppStorage、LocalStorage六种装饰器组合以解决不同范围内的组件间状态共享。按照共享范围能力从小到大,各装饰器组合的共享范围能力和生命周期如下:

  1. @State+@Prop、@State+@Link、@State+@Observed+@ObjectLink:三者的共享范围为从@State所在的组件开始,到@Prop/@Link/ObjectLink所在组件的整条路径,路径上所有的中间组件通过@Prop/@Link/@ObjectLink都可以共享同一个状态。@State修饰的状态和其所属的自定义组件共享生命周期,在组件内定义时创建,组件销毁时被回收。@Link装饰的变量和其所属的自定义组件共享生命周期。@ObjectLink装饰的变量和其所属的自定义组件共享生命周期。(父子
  2. @Provide+@Consume:状态共享范围是以@Provide所在组件为祖先节点的整棵子树,子树上的任意后代组件通过@Consume都可以共享同一个状态。@Provide修饰的变量与其所属的组件绑定,在组件内定义时被创建,在组件销毁时被回收。(根节点为祖先节点以下的子节点都可获取到)
  3. LocalStorage:共享范围为UIAbility内以页面为单位的不同组件树间的共享。存储在LocalStorage中的状态的生命周期与LocalStorage绑定。LocalStorage的声明周期由应用程序决定,当应用释放最后一个指向LocalStorage的引用时,LocalStorage被垃圾回收。(同页面的不同组件树间的共享)
  4. AppStorage:共享范围是应用全局。AppStorage与应用的进程绑定,由UI框架在应用程序启动时创建,当应用进程终止,AppStorage被回收。存储在AppStorage中的状态的生命周期与LocalStorage绑定。(全局变量)

按照软件开发原则,应优先选择共享范围能力小的装饰器方案,减少不同模块间的数据耦合,便于状态及时回收。

建议选择装饰器的优先级为:@State+@Prop、@State+@Link、@State+@Observed+@ObjectLink > @Provide+@Consume > LocalStorage > AppStorage。

减少不必要的参数层层传递

看个示例图

项目中使用Navigation组件管理路由,定义“appNavigationStack”变量表示应用当前的路由信息。现“DiscoverView”组件和“ResourceListView”组件需要共享路由信息状态。按照@State+@Prop层层传递的方案,当前各组件的设计如下:

图7 @State+@Prop当前组件设计图

层层传递,直到两个需要共享状态的组件

若此时产品需要新增功能,该功能要求在“DiscoverView”组件的后代“ActionButtonView”组件上新增对路由信息的判断逻辑。此时开发者需修改上述各个组件设计如下图所示:

图8 @State+@Prop新增功能后组件设计图

可以看到,新功能的逻辑原本只是在“ActionButtonView”这一个组件中使用,开发者却需要修改从“DiscoverView”组件到“ActionButtonView”组件路径上3个组件的结构。若当业务后续再次变更为无需使用该状态时,也同样需要修改多个组件。这显然不是很好的实现方案。

此时使用@Provide+@Consume方案更为合理。同样是“ResourceListView”组件和“DiscoverView”组件共享状态,此方案各组件设计如下:

图9 使用@Provide+@Consume方式当前各组件设计

通过在最顶部组件“MainPage”中注入key值为“appNavigationStack”的路由信息状态,其后代组件均可以通过@Consume装饰器获取该状态值。当业务变动需要“DiscoverView”的后代“ActionButtonView”组件也共享路由信息时,此方案只需在组件“ActionButtonView”上使用@Consume装饰器直接获取路由信息状态,而无需修改其他组件。此时各组件设计如下:

图10 使用@Provide+@Consume方式业务变动后各组件设计

因此当共享状态的组件间跨层级较深时,或共享的信息对于整个组件树是“全局”的存在时,选择@Provide+@Consume的装饰器组合代替层层传递的方式,能够提升代码的可维护性和可拓展性。

按照状态复杂度选择装饰器

  1. @State+@Prop组合方案:
    • @Prop装饰器支持接收Object、class、string、number、boolean、enum类型,以及这些类型的数组。
    • @Prop装饰的变量是对父组件传入状态值的深拷贝,当@Prop装饰器装饰的变量为复杂Object、class或其类型数组时,会增加状态创建时间以及占用大量内存。
    • @Prop装饰的变量和父组件是单向绑定的关系。当父组件数据源发生变化时,接收该数据源的@Prop所在组件的实例会重新渲染。 当该组件内被@Prop装饰的变量被修改时,父组件数据源不会变化,父组件实例也不会重新渲染。
  2. @State+@Link组合方案:
    • @Link装饰器支持接收Object、class、string、number、boolean、enum类型,以及这些类型的数组。
    • @Link装饰器修饰的变量是对父组件传入状态的引用的拷贝,两者指向同一个地址。当状态是简单数据类型或简单Object类型时,@Link和@Prop在状态创建时间和内存的占用方面区别不大。当状态为复杂的Object、class或其类型数组时,@Link相较@Prop能明显减少状态创建时间和内存的占用。
    • @Link装饰器的变量和父组件是双向绑定的关系。当父组件数据源发生变化时,接收该数据源的@Link所在组件的实例会重新渲染。 当该组件内被@Link装饰的变量被修改时,父组件数据源会同步修改,父组件实例也会重新渲染。
  3. @State+@Observed+@ObjectLink组合方案:
    • @ObjectLink只支持接收被@Observed装饰的class实例及继承Date或者Array的class实例。
    • @ObjectLink装饰的变量是只读的,不支持对状态重新赋值。
    • @ObjectLink必须配合@Observed使用,它的设计是为了解决对嵌套类对象属性变化的监听,如需要观察对象数组中单个数据项的属性值变化,或嵌套对象的对象类型属性的子属性变化。

结合三个方案的特性,在选择时有如下建议:

  • 需要观察嵌套类对象的深层属性变化的场景,选择@State+@Observed+@ObjectLink。
  • 状态是复杂对象、类或其类型数组的场景,选择@State+@Link。
  • 状态是简单数据类型时,使用@State+@Link和@State+@Prop均可。在功能层面上,依据@Prop单向绑定的特性,@State+@Prop适合用于非实时修改的场景,如编辑电话薄联系人信息时,展示编辑界面的子组件信息的修改要求不实时同步回父组件,需要等到编辑完成后点击“确认”按钮时才会以事件驱动的方式修改父组件的状态。依据@Link双向绑定的特性,@State+@Link适合用于实时修改的场景,如组件嵌套时的滚动条同步。

总结

在实际开发中,合理选择装饰器主要包含以下三步:

1.首先根据状态需要共享的范围大小,尽量选择共享能力小的装饰器方案,优先级依次为@State+@Prop、@State+@Link或@State+@Observed+@ObjectLink > @Provide+@Consume > LocalStorage > AppStorage。

2.当共享的状态的组件间层级相差较大时,为避免较差的代码可扩展性和可维护性,@Provide+@Consume的方案要优于层层传递的共享方案。

3.对于具有相同优先级的@State+@Prop、@State+@Link或@State+@Observed+@ObjectLink 三个方案,应结合状态的复杂程度和装饰器各自的特性选择。

实际开发中,应根据业务需求衡量优先级选择合适的装饰器,整体可参考如下建议:

  1. @State+@Prop:适合状态结构简单,且共享状态的组件间层级相差不大的场景。或功能上要求子组件不实时同步修改给父组件的场景。
  2. @State+@Link:适合状态结构复杂,且共享状态的组件间层级相差不大的场景。或功能上要求子组件对状态的修改实时同步给父组件的场景。
  3. @State+@Observed+@ObjectLink:适合需要观察嵌套类对象的子属性变化的场景或对象数组的数据项属性变化的场景,如监听列表卡片上某个属性的变化。
  4. @Provide+@Consume:适合用于对于整个组件树而言“全局”的状态,且该状态改动不频繁的状态共享场景,如共享界面的路由信息。
  5. AppStorage:适合对于整个应用而言“全局”的变量或应用的主线程内多个UIAbility实例间的状态共享,如用户信息。
  6. LocalStorage:适合对于单个Ability而言“全局”的变量,主要用于不同页面间的状态共享场景。

 精细化拆分复杂状态

第一种方式

使用AppStorage存储用户信息UserData,将收藏的id加入到UserData这个类中 那么探索页面的收藏发生改变 我的页面自然同步 但是有一点不好  我的页面一旦我的信息发生修改 那么AppStorage存储用户信息UserData一旦监听到修改就会同步更新探索和我的页面  其实探索页根本不需要存储用户信息只需要存储收藏的id数组就行 这样我们就分开存储 

单独存储下id就好了 在此方案中,由于文章卡片组件没有绑定AppStorage中key值为“userData”的变量,当用户编辑修改了用户描述userData.description的值时, 文章卡片组件不会重新渲染。

 因此,从性能的角度考虑,在使用LocalStorage或AppStorage装饰器存储状态变量时需要合理设计状态的数据结构,避免无意义的渲染刷新。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1959628.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

细说MCU的DAC1和DAC2各自输出一通道模拟信号的方法

目录 一、参考硬件 二、 建立新工程 1.配置DAC1 2.配置DAC1的DMA 3.配置DAC2 4.配置DAC2的DMA 5.配置定时器 6.配置时钟和Debug 三、修改代码 四、 查看结果 一、参考硬件 本项目依赖的软件和硬件工程参考本文作者写的文章: 细说MCU的DAC1实现…

【中项第三版】系统集成项目管理工程师 | 第 11 章 规划过程组⑧ | 11.21 - 11.22

前言 第11章对应的内容选择题和案例分析都会进行考查,这一章节属于10大管理的内容,学习要以教材为准。本章上午题分值预计在15分。 目录 11.21 实施定量风险分析 11.21.1 主要输入 11.21.2 主要工具与技术 11.21.3 主要输出 11.22 规划风险应对 …

UPLOAD-LABS靶场[超详细通关教程,通关攻略]

---------------------------------------- 靶场环境: 下载链接: https://codeload.github.com/c0ny1/upload-labs/zip/refs/heads/master 使用小皮集成环境来完成这个靶场 将文件放到WWW目录下就可以进行访问 ------------------------------------…

【JavaEE】HTTP(3)

🤡🤡🤡个人主页🤡🤡🤡 🤡🤡🤡JavaEE专栏🤡🤡🤡 文章目录 1.HTTP响应1.2状态码 2.HTTPS协议2.1概念2.2引入对称加密2.2.1概念2.2.2图解…

Ribbon-微服务注册中心(Ribbon概述 基于Ribbon实现订单调⽤商品服务 服务调⽤Ribbon⾼级 )

目录 一、Ribbon概述 1. 什么是Ribbon 2. Ribbon的主要作⽤ 二、基于Ribbon实现订单调⽤商品服务 1. 坐标依赖 2. ⼯程改造 三、服务调⽤Ribbon⾼级 1. 负载均衡概述 2. 客户端负载均衡与服务端负载均衡 3. 基于Ribbon实现负载均衡 3.1 搭建多服务实例 3.2 负载均衡…

完蛋!我把AI喂吐了!

当我们用 [RAG] 构建一个知识库问答应用的时候,总是希望知识库里面灌的数据越多,问答的效果越好,事实真是如此吗?这篇文章给大家答案。 引言 在人工智能问答系统的发展中,RAG(Retrieval-Augmented Generat…

努比亚开局连发两款旗舰机,其中一款还能卫星通话?

在智能手机市场竞争日益激烈的当下,努比亚作为国内知名手机品牌,始终致力于为消费者带来兼具创新性和实用性的产品。 近日,努比亚正式发布了两款备受瞩目的旗舰手机——努比亚Z60 Ultra领先版和努比亚Z60S Pro。两款手机不仅在硬件配置上实现…

Macbook Pro升级macOS 10.15及以上的全过程

Author : Spinach | GHB Link : http://blog.csdn.net/bocai8058文章目录 前言升级步骤选择指定macOS版本并下载安装升级macOS安装过程安装完成 前言 由于现在更多软件安装所需系统要求10.15及以上,导致很多app应用不能使用,如edge mac的操作系统要求…

LlamaIndex vs LangChain: 理解关键差异

LLM(大型语言模型)已成为各行各业不可或缺的工具,用于生成类人文本、翻译语言和回答问题等任务。有时,LLM的响应令人惊叹,因为它们比人类更迅速、更准确。这表明了它们对当今技术格局的重大影响。 今天让我们聊聊 Llam…

i2c中结构体 数据传输 i2c Tools使用

I2C中重要结构体 在I2C(Inter-Integrated Circuit)通信中,涉及的主要结构体通常用于描述设备、消息和传输的配置。以下是一些常见的I2C结构体及其作用: i2c_adapter: 这是一个代表I2C总线适配器的结构体。它包含与该I2C总线相关的…

【Django5】模型定义与使用

系列文章目录 第一章 Django使用的基础知识 第二章 setting.py文件的配置 第三章 路由的定义与使用 第四章 视图的定义与使用 第五章 二进制文件下载响应 第六章 Http请求&HttpRequest请求类 第七章 会话管理(Cookies&Session) 第八章 文件上传…

【ai】 2005年 rule based expert system学习笔记1

PPT 是2005年的? Negnevitsky, Pearson Education 使用两种推理引擎的选择 backward chaining(逆向链接)推理过程 backward chaining(逆向链接)推理过程的GPT解释 这幅图展示了一个基于规则的专家系统如何通过backward chaining(逆向链接)推理过程来达到最终的推理目标…

[tomato]靶机复现漏洞详解!

靶机地址: https://download.vulnhub.com/tomato/Tomato.ova 靶机环境:Vmware 网络:NAT模式 信息收集: arp-scan -l 扫描靶机ip地址 扫描开放的端口信息 nmap -sS -sV -p- 192.168.77.135 发现开放端口21&#xff…

Matplotlib柱形图大揭秘:让数据‘站’起来,比增高鞋垫还管用!

1. Matplotlib绘制柱形图/柱状图/条形图 柱状图是一种用矩形柱来表示数据分类的图表,柱状图可以垂直绘制,也可以水平绘制,它的高度与其表示的数据成正比关系 # 导包 import numpy as np import pandas as pd import matplotlib.pyplot as p…

黑马Java零基础视频教程精华部分_9_面向对象进阶(1)

系列文章目录 文章目录 系列文章目录一、static(表示静态) 是Java中的一个修饰符,可以修饰成员方法,成员变量1、静态变量2、静态变量底层原理3、static静态方法4、工具类、测试类、Javabean类5、static注意事项从代码层面从内存层面 6、重新认识main方法…

[ WARN:0@0.014] global loadsave.cpp:248 cv::findDecoder imread_

[ WARN:00.014] global loadsave.cpp:248 cv::findDecoder imread_ 目录 [ WARN:00.014] global loadsave.cpp:248 cv::findDecoder imread_ 【常见模块错误】 【解决方案】 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页,我是博主英杰…

网工必装软件,SecureCRT从零到精通,不可错过

号主:老杨丨11年资深网络工程师,更多网工提升干货,请关注公众号:网络工程师俱乐部 中午好,我的网工朋友。 相信在平时的日常工作中,大家经常需要通过安全的方式远程访问各种设备和服务。SecureCRT作为一款强…

JavaWeb的三层架构和分层解耦

博客主页:音符犹如代码系列专栏:JavaWeb关注博主,后期持续更新系列文章如果有错误感谢请大家批评指出,及时修改感谢大家点赞👍收藏⭐评论✍ 目录 三层架构 分层解耦 三层架构是哪三层? Controller:表现层…

云微客短视频矩阵能带来流量吗?有哪些产品特色?

短视频平台,现如今已经成为了互联网最大的流量池,诸如抖音、快手、小红书、视频号、哔哩哔哩等平台,日活量都在上亿。短视频赛道汇聚了无数的用户群体,所以商企品牌的营销定位就应该在这里。 许多企业看到了这样的营销商机&#x…

AI绘画模型之:CLIP 与 DALL-E 2

重磅推荐专栏: 《大模型AIGC》 《课程大纲》 《知识星球》 本专栏致力于探索和讨论当今最前沿的技术趋势和应用领域,包括但不限于ChatGPT和Stable Diffusion等。我们将深入研究大型模型的开发和应用,以及与之相关的人工智能生成内容(AIGC)技术。通过深入的技术解析和实践经…