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组件实现背包物品的拖拽以及将一个背包的物品拖拽到另外一个背包中。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++ | Leetcode C++题解之第160题相交链表

题目&#xff1a; 题解&#xff1a; class Solution { public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {if (headA nullptr || headB nullptr) {return nullptr;}ListNode *pA headA, *pB headB;while (pA ! pB) {pA pA nullptr ? headB : p…

Axios进阶

目录 axios实例 axios请求配置 拦截器 请求拦截器 响应拦截器 取消请求 axios不仅仅是简单的用基础请求用法的形式向服务器请求数据&#xff0c;一旦请求的端口与次数变多之后&#xff0c;简单的请求用法会有些许麻烦。所以&#xff0c;axios允许我们进行创建axios实例、ax…

LeetCode | 344.反转字符串

设置头尾两个指针&#xff0c;依靠中间变量temp交换头尾指针所指元素&#xff0c;头指针后移&#xff0c;尾指针前移&#xff0c;直到头尾指针重合或者头指针在尾指针后面一个元素 class Solution(object):def reverseString(self, s):""":type s: List[str]:r…

Gone框架介绍26 - Gone v1.x 版本 正式发布,更加强大的依赖注入,更加卓越的执行效率

gone是可以高效开发Web服务的Golang依赖注入框架 github地址&#xff1a;https://github.com/gone-io/gone 文档地址&#xff1a;https://goner.fun/zh/ 文章目录 优化和新特性gone 核心功能增强内置Goners覆盖测试 后续计划 优化和新特性 gone 核心功能增强 重构了函数参数依…

关于HTTP劫持,该如何理解、防范和应对

一、引言 HTTP劫持&#xff08;HTTP Hijacking&#xff09;是一种网络安全威胁&#xff0c;它发生在HTTP通信过程中&#xff0c;攻击者试图通过拦截、篡改或监控用户与服务器之间的数据流量&#xff0c;以达到窃取敏感信息或执行恶意操作的目的。今天我们就来详细了解HTTP劫持…

C语言 | Leetcode C语言题解之第160题相交链表

题目&#xff1a; 题解&#xff1a; struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {if (headA NULL || headB NULL) {return NULL;}struct ListNode *pA headA, *pB headB;while (pA ! pB) {pA pA NULL ? headB : pA->ne…

express+vue在线im实现【二】

expressvue在线im实现【一】 在线体验 本期完成了&#xff1a; 1、心跳检测 2、支持发送表情与图片【这个目前还需要优化下&#xff0c;当图片上传后会被默认选中&#xff0c;需要点击一下旁边&#xff0c;使之失去选中效果&#xff0c;才能正常&#xff0c;留待下期优化吧】…

基于Quartus Prime18.1的安装与FPGA的基础仿真教程

Quartus是一种美国科技公司Intel&#xff08;英特尔&#xff09;公司开发的FPGA&#xff08;现场可编辑门阵列&#xff09;设计编译软件&#xff0c;用作设计、仿真、综合和布局、支持多种编程语言&#xff0c;包括VHDL、Verilog等&#xff0c;并具有丰富的功能和工具库&#x…

17.Meta AI 大模型家族 LLaMA

Meta LLaMA 1 大模型技术解读 LLaMA 1&#xff1a;小模型大数据 LLaMA 1 在万亿 Token 公开数据集上预训练 LLaMA 1 模型网络架构改进 大模型网络架构差异性配置总览 典型大模型网络架构对比 LLaMA 1 预训练超参数配置 典型大模型训练超参数对比 LLaMA 1 预训练效率提升与成本…

net start mysql服务名无效

问题背景 起因是我的电脑因为停电烧坏了系统固态硬盘&#xff0c;再新装系统后&#xff0c;之前的MySQL服务无法通过下面的命令启动。 net start mysql # 报错&#xff1a;服务名无效 报错&#xff1a;服务名无效 报错信息 未找到&#xff1a;在Windows服务中找不到MySQL 找…

增强大型语言模型(LLM)可访问性:深入探究在单块AMD GPU上通过QLoRA微调Llama 2的过程

Enhancing LLM Accessibility: A Deep Dive into QLoRA Through Fine-tuning Llama 2 on a single AMD GPU — ROCm Blogs 基于之前的博客《使用LoRA微调Llama 2》的内容&#xff0c;我们深入研究了一种称为量化低秩调整&#xff08;QLoRA&#xff09;的参数高效微调&#xff0…

【APP_汽修宝】数据采集案例APP_数据解密分析

如果不会写代码&#xff0c;那就出书、写博客、做视频、录播客。 &#x1f4da; S35赛季末王者昭君罗 关键代码定位 使用方法【逆向-快速定位关键代码】通过hook常用函数HashMap方法 动态分析 下面是我们通过访问目标页面时 Frida hook 捕获HashMap的调…

Nginx与Gateway

Nginx与Gateway Nginx 基本介绍 Nginx 是一款轻量级的高性能 Web 服务器/反向代理服务器及电子邮件&#xff08;IMAP/POP3&#xff09;代理服务器。它由俄罗斯的 Igor Sysoev 所开发&#xff0c;最初供俄罗斯大型的门户网站及搜索引擎 Rambler 使用。 Nginx 的特点在于其占用…

RIP解决不连续子网问题

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

从xxl-job源码中学习Netty的使用

1. 启动与Spring实例化 com.xxl.job.core.executor.impl.XxlJobSpringExecutor.java类 继承SmartInitializingSingleton 类&#xff0c;在afterSingletonsInstantiated 实例化后方法中 调用initJobHandlerMethodRepository 把所有的xxljob任务管理起来&#xff1b; private…

.net8系列-图文并茂手把手教你使用Nlog记录.net日志

Nlog是什么&#xff1f; NLog是一个为.NET平台设计的灵活且免费的日志记录库。它适用于包括.NET Framework、.NET Core和.NET Standard在内的多种.NET环境。 Nlog有什么好处或者特点&#xff1f; 配置灵活&#xff1a;NLog允许开发者通过配置文件&#xff08;通常是NLog.conf…

串口触摸屏分割字符串

分割字符串的方法1、split2、indexOf()3、substr(start,length) 分割字符串的方法 1、split&#xff1a;将一个字符串分割为子字符串&#xff0c;然后将结果作为字符串数组返回。 2、indexOf() &#xff1a;返回某个指定的字符串值在字符串中首次出现的位置&#xff08;从左向右…

机器人、人工智能相关领域 news/events (专栏目录)

Some Insights 一些机器人、人工智能或相关领域的news、events等 1. 智能制造 - 你需要了解的 10 个基本要素 2. 现实世界中的人工智能&#xff1a;工业制造的 4 个成功案例研究 3. 企业使用人工智能情况调查 4. 未来工厂中的人工智能&#xff1a;人工智能加速制造成果规模…

用React编写一个密码组件表单

theme: condensed-night-purple highlight: atelier-cave-light 背景介绍 我们在使用网站或者应用程序的登录界面或创建帐户界面时&#xff0c;往往避免不了需要用户输入密码这一步骤&#xff0c;而用户是否可以选择看见他们输入的密码是十分重要的一项功能。尤其是在当输入的…

QT绘图项目 - 汽车表盘

目录 前言: 整体代码 widget.h widget.cpp 效果演示 实现刻度文字正确排版 优化代码 达到效果 封装整理代码结构: widget.h widget.cpp 指针样式美化 优化后的指针API 效果演示 设置高速刻度为红色 优化刻度API 效果演示 速度显示优化 给内圈画上黑色 优化速度…