UniVue更新日志:使用ObservableList优化LoopList/LoopGrid组件的使用

github仓库

稳定版本仓库:https://github.com/Avalon712/UniVue

开发版本仓库:https://github.com/Avalon712/UniVue-Develop

UniVue扩展框架-UniVue源生成器仓库:https://github.com/Avalon712/UniVue-SourceGenerator

更新说明

如果大家有在使用之前的版本或学习之前的版本一定要进行更新到至少是今天的版本,因为今天发现了一个过去的版本的一个重大的BUG(就是视图的BindModel()函数有可能会重复生成UIBundle,这个BUG配合LoopList和LoopGrid组件的功能,会导致UIBundle数量一直在重复叠加生成,非常严重的BUG。一定要记得更新。)

组件功能与使用介绍

UniVue中提供的LoopList和LoopGrid组件是UniVue中重要的组件。首先他们都是依赖UGUI的ScrollRect组件实现的可复用Item的滚动视图(即:如果背包有1000个物品,实际上实例化的GameObject的数量=可视域内的行数*可视域内的列数cols+一行或一列的数量,比如:可视域内只能看见6*6个格子,那么实际的生成的GameObject数量为6*7或7*6,至于是6*7还是7*6取决于滚动方向。对于ListWidget生成的数量也是同样的道理即比可视域的数量多一个)。其中ListWidget提供无限滚动的功能(感觉这个功能应该会用得很少,但是考虑到可以使用这个组件的无限循环滚动功能实现轮播图的效果就保留了),GridWidget则没有提供,因为我相信真实项目中一定不会用到一个背包去无限循环滚动的功能。

关于UniVue中使用的所有例子都能在UniVue-Develop(https://github.com/Avalon712/UniVue-Develop)这个仓库中看到。下面是两个组件的使用:

 两个组件都支持水平滚动和垂直滚动。通过右上方的输出调试信息可以看见Views的数量。由于这两个组件会将ScrollRect的Content下的每个Item都创建一个FlexibleView,因此从这个这个View的数量可以看见实际实例化的GameObject数量。

另外这两个组件不依赖任何Unity中的布局组件,而是内部实现得有一套布局逻辑。

注意:ScrollRect的Content这个GameObject的锚点一定要设置合理。content的布局设置如下面的两个图。(同时content下的第一个Item必须存在,且锚点设置必须为左上角,位置为(0,0,0),因为后面实例化其它Item的GameObject时会将第一个Item作为预制体进行实例化)。

垂直滚动时Content的锚点设置类型

水平滚动时Content的锚点设置

Content下的第一个Item的锚点设置

这两个组件再搭配上UniVue的数据模型双向绑定的功能,就能够实现数据的自更新,UI的实时响应。而且实现所有上述的功能大概你需要写的代码数量就是两行。一行创建视图,一行绑定数据。

关于性能方法,这是完全没得说的,我已经优化到极致了。没有使用什么对象池以及其它的功能,关于具体如何实现的,后面再将吧。

但是今天更新的内容一是优化的这两个组件的视图刷新逻辑和数据重新绑定。同时另外一个重大的更新是使用了UniVue中的ObservableList数据结构优化了之前再绑定List数据会对绑定的List数据进行拷贝(本次更新任然保留了这种模式,但是建议大家使用ObervableList的方式)。使用ObservableList能够完全实现数据驱动式。如果不使用ObservableList,采用原来的List方法,可能每次添加新数据、移除新数据、对数据排序、改变数据的顺序你都要进行两步操作:一是改变你自己维护的那么List数据,二是改变组件内部的维护的List数据。这样真的很麻烦,而且会对List进行拷贝的方式,如果要绑定的数据本来就很多,现在还要拷贝一份。我忍受不了这种低效的方式,所有设计了一个新的List集合来优化上面的低效。

ObservableList<T>数据结构的实现

这个集合的实现其实就是对C#自带的List进行包装修饰(装饰器模式),核心功能和List是一样的,但是对List的一些对数据内容的修改进行了封装,能够实现实现当内容发生改变时自动调用回调函数。这个类的使用和List的使用完全一样,List所有支持的操作它都能进行。同时支持注册回调事件、以及实现Java中将List变为一个不可变的集合(变为不可变的集合后,后面对集合内容的修改都会抛出异常)。其中提供的List扩展功能就是IObservableList接口定义的功能。ObservableList<T>这个类的实现代码太长了,建议大家可以去源码中查看,这个类定义在UniVue>Runtime>Utils>Extensions这个目录下,命名空间为UniVue.Utils。

    /// <summary>/// 事件调用顺序:OnAdded | OnRemoved | OnReplaced  ----> OnChanged/// </summary>public interface IObservableList{/// <summary>/// 获得当前回调函数的观察者的id/// </summary>/// <remarks>没有的话将返回int.MinValue</remarks>int CurrentObserverId { get; }int Capacity { get; set; }int Count { get; }V Get<V>(int index);void Set<V>(V item, int index);void Add<V>(V item);bool Remove<V>(V item);bool Contains<V>(V item);void RemoveAt(int index);int IndexOf<V>(V item);void Sort();void Sort<V>(IComparer<V> comparer);/// <summary>/// 当集合内容发生改变时调用(包括元素的增加、删除、替换、顺序改变)/// </summary>void AddListener_OnChanged(int observerId, Action<NotificationMode> onChanged);/// <summary>/// 当有元素被移除时回调(arg0: 被移除的元素 arg1: 被移除元素的索引;)/// </summary>void AddListener_OnRemoved<V>(int observerId, Action<V, int> onRemoved);/// <summary>/// 当有新数据添加时回调/// </summary>void AddListener_OnAdded<V>(int observerId, Action<V> onAdded);/// <summary>/// 当元素被替换时回调。arg0是元素的索引;arg1是替换前的元素;arg2是替换后的元素/// </summary>void AddListener_OnReplaced<V>(int observerId, Action<int, V, V> onReplaced);void ClearObservers();void RemoveListeners(int observerId);/// <summary>/// 当集合内容发生改变时调用(包括元素的增加、删除、替换、顺序改变)/// </summary>void RemoveListener_OnChanged(int observerId);/// <summary>/// 当有元素被移除时回调(arg0: 被移除元素的索引; arg1: 被移除的元素)/// </summary>void RemoveListener_OnRemoved(int observerId);/// <summary>/// 当有新数据添加时回调/// </summary>void RemoveListener_OnAdded(int observerId);/// <summary>/// 当元素被替换时回调。arg0是元素的索引;arg1是替换前的元素;arg2是替换后的元素/// </summary>void RemoveListener_OnReplaced(int observerId);}

关于这种观察者模式、装饰器模式等等在UniVue中使用得非常多。以及为了防止各种值类型装箱操作内部有时候会使用很深的装饰器模式以及多态的使用。

下期功能更新预告 

使用SuperGrid组件实现背包物品的拖拽以及将一个背包的物品拖拽到另外一个背包中。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【电机控制】FOC算法验证步骤——PWM、ADC

【电机控制】FOC算法验证步骤 文章目录 前言一、PWM——不接电机1、PWMA-H-50%2、PWMB-H-25%3、PWMC-H-0%4、PWMA-L-50%5、PWMB-L-75%6、PWMC-L-100% 二、ADC——不接电机1.电流零点稳定性、ADC读取的OFFSET2.电流钳准备3.运放电路分析1.电路OFFSET2.AOP3.采样电路的采样值范围…

小白Linux提权

1.脏牛提权 原因&#xff1a; 内存子系统处理写入复制时&#xff0c;发生内存条件竞争&#xff0c;任务执行顺序异常&#xff0c;可导致应用崩溃&#xff0c;进一步执行其他代码。get_user_page内核函数在处理Copy-on-Write(以下使用COW表示)的过程中&#xff0c;可能产出竞态…

基于文本和图片输入的3D数字人化身生成技术解析

随着虚拟现实、增强现实和元宇宙等技术的飞速发展,对高度逼真且具有表现力的3D数字人化身的需求日益增长。传统的3D数字人生成方法往往需要依赖大量的3D数据集,这不仅增加了数据收集和处理的成本,还限制了生成的多样性和灵活性。为了克服这些挑战,我们提出了一种基于文本提…

Cocos Creator,Youtube 小游戏!

YouTube 官方前段时间发布了一则重磅通知&#xff0c;宣布平台旗下小游戏功能 Youtube Playables 正式登录全平台&#xff08;安卓、iOS、网页&#xff09;&#xff0c;并内置了数十款精选小游戏。 Youtube Playables 入口&#xff1a; https://www.youtube.com/playables Coco…

使用 C# 学习面向对象编程:第 7 部分

多态性 我们在程序中使用多态的频率是多少&#xff1f;多态是面向对象编程语言的第三大支柱&#xff0c;我们几乎每天都在使用它&#xff0c;却不去想它。 这是一个非常简单的图表&#xff0c;它将解释多态性本身。 简单来说&#xff0c;我们可以说&#xff0c;只要我们重载类…

【解决方案】数据采集工作站数据传不上去?

数据采集工作站扮演着至关重要的角色&#xff0c;它们负责收集、处理和传输各种传感器和设备的数据。然而&#xff0c;有时会遇到数据传输失败的问题。本文将详细探讨数据采集工作站数据传不上去的可能原因及其解决方案。&#xff08;更多了解采集器设备可前往苏州稳联&#xf…

【面试干货】Class.forName()与ClassLoader.loadClass()在Java反射中的区别

【面试干货】Class.forName&#xff08;&#xff09;与ClassLoader.loadClass&#xff08;&#xff09; 在Java反射中的区别 1、Class.forName()1.1 示例代码1.2 关键点 2、ClassLoader.loadClass()2.1 示例代码2.2 关键点 3、两者之间的区别 &#x1f496;The Begin&#x1f…

Training language models to follow instructions with human feedback 论文阅读

论文原文&#xff1a;https://arxiv.org/pdf/2203.02155 论文简介 语言模型越大并不意味着它能更好的理解用户的意图&#xff0c;因此在这篇论文中&#xff0c;展示了根据人的反馈对模型进行微调&#xff0c;使得语言模型能够在各种人物上更好的理解用户的意图。在评估中&…

【C++】模板进阶(特化)

&#x1f308;个人主页&#xff1a;秦jh_-CSDN博客&#x1f525; 系列专栏&#xff1a;https://blog.csdn.net/qinjh_/category_12575764.html?spm1001.2014.3001.5482 目录 非类型模板参数 数组越界检查 按需实例化 模板的特化 函数模板特化 类模板特化 全特化 ​…

LabVIEW故障预测

在LabVIEW故障预测中&#xff0c;振动信号特征提取的关键技术主要包括以下几个方面&#xff1a; 时域特征提取&#xff1a;时域特征是直接从振动信号的时间序列中提取的特征。常见的时域特征包括振动信号的均值、方差、峰值、峰-峰值、均方根、脉冲指数等。这些特征能够反映振动…

【文末附gpt升级秘笈】AI热潮降温与AGI场景普及的局限性

AI热潮降温与AGI场景普及的局限性 摘要&#xff1a; 随着人工智能&#xff08;AI&#xff09;技术的迅猛发展&#xff0c;AI热一度席卷全球&#xff0c;引发了广泛的关注和讨论。然而&#xff0c;近期一些学者和行业专家对AI的发展前景提出了质疑&#xff0c;认为AI热潮将逐渐…

如何警用root用户登录ssh

使用tail指令&#xff0c;可以动态查看日志信息。 &#xff08;tail -f /var/log/secure或messages&#xff09; 使用>符号&#xff0c;可以清空日志内容&#xff0c;不删除文件本身。 禁用root用户为以下步骤&#xff1a; 首先使用useradd创建用户&#xff08;可以修改为其…

路由器虚拟服务器有什么作用

现如今在IPv4时代&#xff0c;由于公网IP地址的匮乏&#xff0c;约有70%的电脑都处于内网中&#xff0c;上网需要通过路由器。如果反过来想要访问身处内网的电脑&#xff0c;我们就需要在路由器里开放相应的端口才能实现。而这开放端口的功能&#xff0c;在路由器里就叫做虚拟服…

俄罗斯Yandex推广投放如何开户?Yandex广告开户和代运营推广流程详解_俄罗斯_受众_搜索引擎

在俄罗斯进行Yandex广告推广是一种有效的在线营销方式&#xff0c;特别是针对俄罗斯市场。Yandex是俄罗斯最受欢迎的搜索引擎&#xff0c;类似于Google在全球范围内的地位。以下是通过Yandex广告推广的一般步骤&#xff0c;以及如何通过上海上弦进行广告开户和代运营。 1. Yan…

GPT_AI高速发展中什么是Prompt提示词?

提示词&#xff08;Prompt&#xff09;是给大语言模型&#xff08;以下简称模型&#xff09;的输入文本&#xff0c;用于指定模型应该执行什么样的任务并生成什么样的输出。 提示词发挥了“提示” 模型 应该做什么的作用。设计高质量的提示词需要根据目标任务和模型能力进行精…

49.Python-web框架-Django解决多语言redirect时把post改为get的问题

目录 1.背景 2.思路 3.寻找 Find and Replace 4.再次运行程序&#xff0c;POST来了 5.小结 1.背景 昨天在练习一个Django功能时&#xff0c;把form的method设置为POST&#xff0c;但是实际提交时&#xff0c;一直是GET方法。最后发现这是与多语言相关&#xff0c;django前面…

架构设计 - MySQL 插入数据性能优化策略

mysql 数据库提高数据插入效率主要可以考虑以下方面&#xff1a; 使用批量插入数据的 SQL 语句&#xff0c;避免使用 for 循环逐条记录插入。 所有插入语句共用一个事务&#xff0c;避免1条SQL语句开1个事务&#xff0c;所有操作都完成后再提交事务。 尽量按照索引递增顺序插入…

【JVM】JVisualVM的介绍、使用和GC过程

VisualVM介绍 VisualVM 是Netbeans的profile子项目&#xff0c;已在JDK6.0 update 7 中自带&#xff0c;能够监控线程&#xff0c;内存情况&#xff0c;查看方法的CPU时间和内存中的对 象&#xff0c;已被GC的对象&#xff0c;反向查看分配的堆栈(如100个String对象分别由哪几…

【Python/Pytorch - 网络模型】-- SVD算法

文章目录 文章目录 00 写在前面01 基于Pytorch版本的SVD算代码02 理论知识 00 写在前面 &#xff08;1&#xff09;矩阵的奇异值分解在最优化问题、特征值问题、最小二乘方问题、广义逆矩阵问题及统计学等方面都有重要应用&#xff1b; &#xff08;2&#xff09;应用&#…

看穿人性!现货白银交易的一些博弈心得

很多投资者认为现货白银交易最应该讲求的是交易技巧&#xff0c;但交易的技巧和套路是“死”的&#xff0c;行情走势却是“活”的&#xff0c;投资者需要在实践中不断地累积经验和总结心得&#xff0c;才能更加灵活地面对行情走势的变化&#xff0c;逐步达至盈利的理想彼岸。 无…