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

news2024/11/25 3:51:17

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.coloradmin.cn/o/1830160.html

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

相关文章

Django REST framework视图集与路由详解:深入理解ViewSet、ModelViewSet与路由映射器

系列文章目录 Django入门全攻略&#xff1a;从零搭建你的第一个Web项目Django ORM入门指南&#xff1a;从概念到实践&#xff0c;掌握模型创建、迁移与视图操作Django ORM实战&#xff1a;模型字段与元选项配置&#xff0c;以及链式过滤与QF查询详解Django ORM深度游&#xff…

【java】数学运算考试系统

目录 一、登录界面&#xff1a; 二、管理员界面&#xff1a; 三、学生考试界面&#xff1a; 面向小学低年级学生&#xff0c;随机生成两个整数的加减法算式要求学生解答。要求有用 户登录、注册等 GUI 界面&#xff0c;用户数据存入文件&#xff0c;体现面向对象编程思想。 …

windows11子系统Ubuntu 22.04.4子安装图形化界面

1、windows11家庭版本设置 打开虚拟机安装许可 2、Microsoft Store下载安装ubuntu 我使用的是22.04.4 LTS版本 3、 打开ubuntu 命令窗口 1、打开win11的命令行&#xff0c;在下拉三角下标&#xff0c;打开&#xff0c;可以看到有Ubuntu 的选项&#xff0c;点击即可进入linux命…

【Android面试八股文】你说一说什么是双亲委托机制?为什么需要双亲委托机制?

一、双亲委托机制 1.1 双亲委托机制概述 双亲委托机制是指当一个类加载器收到一个类加载请求时, 该类加载器首先会把请求委派给父类加载器。 如果父类加载器还存在父类加载器,则会一直向上委派,直至最终交由顶层的启动类加载器完成类加载, 每个类加载器都是如此,只有在所…

RIP解决不连续子网问题

#交换设备 RIP解决不连续子网问题 一、不连续子网的概念 相同主网下的子网&#xff0c;被另一个主网分割&#xff0c;例如下面实验拓扑在某公司的网络整改项目中&#xff0c;原先R1 和RS 属于同一主网络 10.0.0.0/8&#xff0c;现被 R2、R3、R4 分离&#xff0c;整网采用了 …

Docker 安装 MySQL5.7 和 MySQL8

文章目录 安装 MySQL5.7拉取镜像前期准备启动容器 安装MySQL8.0拉取镜像查看镜像前期准备启动容器 安装 MySQL5.7 拉取镜像 docker pull mysql:5.7拉下来镜像后 执行 docker images 此时我们已经有这个镜像了。 前期准备 在根目录下创建 app &#xff0c; 在 app 目录下创建…

牛客周赛 Round 47 解题报告 | 珂学家

前言 题解 这真的是牛客周赛&#xff1f; 哭了 欢迎关注 珂朵莉 牛客周赛专栏 珂朵莉 牛客小白月赛专栏 A. 小红的葫芦 签到题 但是写起来有点变扭&#xff0c;方法应该蛮多的 统计分组 有2组一组长度为2&#xff0c;一组长度为3 def check(arr):arr.sort()if arr[0] …

数据结构试题 20-21

真需要就死记吧 二叉树遍历-先序(非递归)【图解代码】_哔哩哔哩_bilibili 解释一下步骤&#xff1a; 一个循环为&#xff1a; 1.取节点 2.放右子树 3.放左子树 每次循环&#xff0c;都要从栈里取出一个节点 先放右子树&#xff0c;再放左子树 那这道题就是&#xff0c;先放1&am…

内网Docker镜像无法使用?Debian/Ubuntu离线安装Dokcer

离线安装Docker 卸载冲突的包 for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done先删除docker sudo apt-get purge docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin d…

DSP28335:独立按键控制LED灯

做任何事情不可操之过急&#xff0c;虽然我们可能在之前的单片机学过相关的原理&#xff0c;但是一个新的单片机依然有他的学习的地方&#xff0c;之前我觉得很简单&#xff0c;就跳过这个学习&#xff0c;结果到后面就很浮躁&#xff0c;导致后面的内容与这一章相连接的时候&a…

调用第三方系统的签名设计与校验实例讲解与实践

在现代软件开发中&#xff0c;调用第三方系统API已经成为常见需求。为了保证数据传输的安全性和完整性&#xff0c;许多API采用了签名机制。本文将详细讲解如何设计与校验调用第三方系统的签名&#xff0c;以确保双方通信的安全和可靠。 #### 一、签名机制的意义 签名机制主要…

.gitignore文件忽略的内容不生效问题解决

文章目录 ①&#xff1a;现象②&#xff1a;原因③&#xff1a;解决 ①&#xff1a;现象 在已经提交过的git管理的项目中&#xff0c; 新增加一个.gitignore文件&#xff0c;文件内忽略内容不生效或者修改.gitignore文件之后&#xff0c;文件内新增的忽略内容不生效 ②&#…

Dell戴尔灵越Inspiron 16 Plus 7640/7630笔记本电脑原装Windows11下载,恢复出厂开箱状态预装OEM系统

灵越16P-7630系统包: 链接&#xff1a;https://pan.baidu.com/s/1Rve5_PF1VO8kAKnAQwP22g?pwdjyqq 提取码&#xff1a;jyqq 灵越16P-7640系统包: 链接&#xff1a;https://pan.baidu.com/s/1B8LeIEKM8IF1xbpMVjy3qg?pwdy9qj 提取码&#xff1a;y9qj 戴尔原装WIN11系…

1.华为路由器-三层交换机-二层交换机组网连接

AR1配置GE 0/0/0接口IP [Huawei]int g0/0/0 [Huawei-GigabitEthernet0/0/0] [Huawei-GigabitEthernet0/0/0]ip add 1.1.1.1 24 [Huawei]iP route-static 192.168.0.0 16 1.1.1.2三层交换机配置如下 创建vlan [Huawei]vlan batch 10 20配置接口ip [Huawei]int g0/0/1 [Huawei…

【数据结构】排序(下)

个人主页~ 排序&#xff08;上&#xff09; 栈和队列 排序 二、常见排序的实现8、快速排序的优化9、非递归快速排序&#xff08;1&#xff09;基本思想&#xff08;2&#xff09;代码实现&#xff08;3&#xff09;时间复杂度&#xff08;4&#xff09;空间复杂度 10、归并排序…

第二篇: 掌握Docker的艺术:深入理解镜像、容器和仓库

掌握Docker的艺术&#xff1a;深入理解镜像、容器和仓库 1. 引言 1.1 简要介绍Docker的重要性 在当今快速发展的技术世界中&#xff0c;软件开发和部署的效率和可靠性是衡量成功的关键因素。Docker&#xff0c;作为一个开源的容器化平台&#xff0c;革新了软件的打包、分发和…

016基于SSM+Jsp的医院远程诊断系统

开发语言&#xff1a;Java框架&#xff1a;ssm技术&#xff1a;JSPJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包…

知识普及:什么是边缘计算(Edge Computing)?

边缘计算是一种分布式计算架构&#xff0c;它将数据处理、存储和服务功能移近数据产生的边缘位置&#xff0c;即接近数据源和用户的位置&#xff0c;而不是依赖中心化的数据中心或云计算平台。边缘计算的核心思想是在靠近终端设备的位置进行数据处理&#xff0c;以降低延迟、减…

如何看懂SparkUI?

Jobs页面 Stage页面 显示额外的指标和摘要指标&#xff1a; 摘要指标&#xff08;Summary Metrics&#xff09;统计了所有完成的任务的执行行为&#xff0c;包括执行时间、GC时间、输入输出信息等&#xff0c;并提供了最小值&#xff08;Min&#xff09;、第25百分位数&#xf…

Windows环境利用 OpenCV 中 CascadeClassifier 分类器识别人脸 c++

Windows环境中配置OpenCV 关于在Windows环境中配置opencv的说明&#xff0c;具体可以参考&#xff1a;VS2022 配置OpenCV开发环境详细教程。 CascadeClassifier 分类器 CascadeClassifier 是 OpenCV 库中的一个类&#xff0c;它用于实现一种快速的物体检测算法&#xff0c;称…