首页 > 其他分享 >QFramework v1.0 使用指南 架构篇:07. 使用 BindableProperty 优化事件

QFramework v1.0 使用指南 架构篇:07. 使用 BindableProperty 优化事件

时间:2022-10-17 10:12:13浏览次数:70  
标签:Count 07 void QFramework v1.0 age public BindableProperty

在这篇我们介绍一个新的概念 BindableProperty。

BindableProperty 是包含 数据 + 数据变更事件 的一个对象。

BindableProperty 基本使用

简单的用法如下:

var age = new BindableProperty<int>(10);

age.Register(newAge=>{
  
  Debug.Log(newAge)
}).UnRegisterWhenGameObjectDestoryed(gameObject);


age++;
age--;


// 输出结果
// 11
// 10

非常简单,就是当调用 age++ 和 age-- 的时候,就会触发数据变更事件。

BindableProperty 除了提供 Register 这个 API 之外,还提供了 RegisterWithInitValue API,意思是 注册时 先把当前值返回过来。

具体用法如下:

var age = new BindableProperty<int>(5);

age.RegisterWithInitValue(newAge => {
  
  Debug.Log(newAge);
  
});

// 输出结果
// 5

这个 API 就是,没有任何变化的情况下,age 先返回一个当前的值,比较方便用于显示初始界面。

BindableProperty 是一个独立的工具,可以脱离 QFramework 架构使用,也就是说不用非要用 QFramework 的 MVC 才能用 BindableProperty,而是可以再自己项目中随意使用。

使用 BindableProperty 优化 CounterApp 的代码

我们直接优化即可,优化后代码如下:

using UnityEngine;
using UnityEngine.UI;

namespace QFramework.Example
{
    
    // 1. 定义一个 Model 对象
    public class CounterAppModel : AbstractModel
    {
        public BindableProperty<int> Count { get; } = new BindableProperty<int>();

        protected override void OnInit()
        {
            var storage = this.GetUtility<Storage>();
            
            // 设置初始值(不触发事件)
            Count.SetValueWithoutEvent(storage.LoadInt(nameof(Count)));

            // 当数据变更时 存储数据
            Count.Register(newCount =>
            {
                storage.SaveInt(nameof(Count),newCount);
            });
        }
    }


    public class AchievementSystem : AbstractSystem 
    {
        protected override void OnInit()
        {
            this.GetModel<CounterAppModel>() // -+
                .Count
                .Register(newCount =>
                {
                    if (newCount == 10)
                    {
                        Debug.Log("触发 点击达人 成就");
                    }
                    else if (newCount == 20)
                    {
                        Debug.Log("触发 点击专家 成就");
                    }
                    else if (newCount == -10)
                    {
                        Debug.Log("触发 点击菜鸟 成就");
                    }
                });
        }
    }

    // 定义 utility 层
    public class Storage : IUtility
    {
        public void SaveInt(string key, int value)
        {
            PlayerPrefs.SetInt(key,value);
        }

        public int LoadInt(string key, int defaultValue = 0)
        {
            return PlayerPrefs.GetInt(key, defaultValue);
        }
    }


    // 2.定义一个架构(提供 MVC、分层、模块管理等)
    public class CounterApp : Architecture<CounterApp>
    {
        protected override void Init()
        {
            // 注册 System 
            this.RegisterSystem(new AchievementSystem()); // +
             
            // 注册 Model
            this.RegisterModel(new CounterAppModel());
            
            // 注册存储工具的对象
            this.RegisterUtility(new Storage());
        }
    }

    // 引入 Command
    public class IncreaseCountCommand : AbstractCommand 
    {
        protected override void OnExecute()
        {
            var model = this.GetModel<CounterAppModel>();
                
            model.Count.Value++; // -+
        }
    }
    
    public class DecreaseCountCommand : AbstractCommand
    {
        protected override void OnExecute()
        {
            this.GetModel<CounterAppModel>().Count.Value--; // -+
        }
    }

    // Controller
    public class CounterAppController : MonoBehaviour , IController /* 3.实现 IController 接口 */
    {
        // View
        private Button mBtnAdd;
        private Button mBtnSub;
        private Text mCountText;
        
        // 4. Model
        private CounterAppModel mModel;

        void Start()
        {
            // 5. 获取模型
            mModel = this.GetModel<CounterAppModel>();
            
            // View 组件获取
            mBtnAdd = transform.Find("BtnAdd").GetComponent<Button>();
            mBtnSub = transform.Find("BtnSub").GetComponent<Button>();
            mCountText = transform.Find("CountText").GetComponent<Text>();
            
            
            // 监听输入
            mBtnAdd.onClick.AddListener(() =>
            {
                // 交互逻辑
                this.SendCommand<IncreaseCountCommand>();
            });
            
            mBtnSub.onClick.AddListener(() =>
            {
                // 交互逻辑
                this.SendCommand(new DecreaseCountCommand(/* 这里可以传参(如果有) */));
            });

            // 表现逻辑
            mModel.Count.RegisterWithInitValue(newCount => // -+
            {
                UpdateView();

            }).UnRegisterWhenGameObjectDestroyed(gameObject);
        }
        
        void UpdateView()
        {
            mCountText.text = mModel.Count.ToString();
        }

        // 3.
        public IArchitecture GetArchitecture()
        {
            return CounterApp.Interface;
        }

        private void OnDestroy()
        {
            // 8. 将 Model 设置为空
            mModel = null;
        }
    }
}

代码改动很多,重要的改动为:

  • Model 中的 Count 和 mCount 改成了一个叫做 Count 的 BindableProperty
  • 删掉了 CountChangeEvent 改用监听 BindableProperty
  • Controller 在初始化中去掉一次 UpdateView 的主动调用

可以说代码量一下子少了很多。

我们看下运行结果:

282fcc3c-96fa-46e1-b4c6-7f4528b04271.gif

运行没问题。

由于我们的 Count 数据,是单个数据 + 事件变更的形式,所以用 BindableProperty 非常合适,可以少写很多代码。

一般情况下,像主角的金币、分数等数据非常适合用 BindableProperty 的方式实现。

好了 BindableProperty 我们就介绍到这里。

更多内容

标签:Count,07,void,QFramework,v1.0,age,public,BindableProperty
From: https://www.cnblogs.com/liangxiegame/p/16798154.html

相关文章