JEvent

JEngine参考Google Java核心库之EventBus编写的事件派发方案

JEvent能干什么?

  • 一键注册类型里的方法
  • 一键派发
  • 取消注册后缓存,方便下次注册
  • 可控线程

命名空间

  • using JEngine.Event;
    

API

  • Register<T>(T val) //从类型中读取需要派发事件的方法\
    
  • Unregister<T>(T val) //取消注册某类型中全部被监听方法
    
  • Post(params object[] parameters) //将参数广播到全部监听方法,只有参数类型匹配的方法才会被调用
    
  • [Subscriber] //监听标签,可以打到类上或方法上,无参数默认主线程派发
    
  • [Subscriber(ThreadMode.Main)] //监听标签,可以打到类上或方法上,Main参数代表主线程派发
    
  • [Subscriber(ThreadMode.Other)] //监听标签,可以打到类上或方法上,Other参数代表子线程派发
    

Demo

参考框架源码的Game场景下,EventDemo的使用,需要搭配ClassBind

using System;
using System.Threading.Tasks;
using JEngine.Core;
using JEngine.Event;
using UnityEngine;
using UnityEngine.UI;

namespace JEngine.Examples
{
    public class EventDemo : JBehaviour
    {
        public UIManager UIManager;

        public override async void Init()
        {
            var ExtensionManager = new ExtensionManager();
            var GMToolsManager = new GMToolsManager();

            //JEvent.ShowLog = true;//是否显示一些log

            JEvent.defaultEvent.Register(UIManager);
            JEvent.defaultEvent.Register(ExtensionManager);
            JEvent.defaultEvent.Register(GMToolsManager);

            //先搞一个登录失败数据
            LoginErrorData d = new LoginErrorData
            {
                username = "test",
                errorMsg = "故意让它错误的",
            };

            //广播错误数据
            JEvent.defaultEvent.Post(d);

            //取消注册ExtensionManager,这样下次不会post到这个实例内的方法
            JEvent.defaultEvent.Unregister(ExtensionManager);

            await Task.Delay(3000);

            //创建独立的JEvent
            JEvent e = new JEvent();

            //登录成功数据
            LoginSuccessData dt = new LoginSuccessData
            {
                username = "杰哥",
                money = 10000
            };

            //给独立的JEvent注册方法
            e.Register(UIManager);
            e.Register(GMToolsManager);
            //广播
            e.Post(dt);
        }
    }

    public class LoginSuccessData
    {
        public string username;
        public int money;
    }

    public class LoginErrorData
    {
        public string username;
        public string errorMsg;
    }

    //监听整个类里面的方法,主线程执行,unity方法必须主线程执行,除了Debug.Log外
    [Subscriber(ThreadMode.Main)]
    public class UIManager
    {
        /*
         * 只要UIManager的实例还在,这些字段就可以用
         */

        public GameObject SuccessPanel;
        public GameObject ErrorPanel;
        public GameObject GamePanel;
        public Text UsernameText;
        public Text MoneyText;
        public Text ErrorMsgText;

        /// <summary>
        /// 登录成功的时候的UI界面更新
        /// </summary>
        /// <param name="data"></param>
        public void OnSuccess(LoginSuccessData data)
        {
            SuccessPanel.SetActive(true);
            new JAction().Delay(3).Do(() =>
            {
                SuccessPanel.SetActive(false);
                UsernameText.text = data.username;
                //因为在GMTools那边更新了money数据,所以用那边的静态实例数据
                //自己写的时候也要注意,每个方法的data参数哪怕进行了更改也不会影响其他方法内的data
                //必须自己把它单独保存到一个其他方法也能读到的地方,才能在其他方法里同步对数据的修改
                //同时多线程处理数据请自行考虑线程安全,脏数据就得自己处理了
                MoneyText.text = $"¥{GMToolsManager.successData.money}";
                GamePanel.SetActive(true);
            })
            .Delay(3)
            .Do(() =>
            {
                GamePanel.transform.parent.gameObject.SetActive(false);
            }).Execute(true);
        }

        /// <summary>
        /// 登录失败的时候的UI界面更新
        /// </summary>
        /// <param name="data"></param>
        public void OnError(LoginErrorData data)
        {
            ErrorMsgText.text = $"账号:{data.username}登录失败,{data.errorMsg}";
            ErrorPanel.SetActive(true);
        }
    }

    //监听整个类里面的方法,子线程执行,不调用unity本身的东西就可以在子线程执行
    [Subscriber(ThreadMode.Other)]
    public class ExtensionManager
    {
        /// <summary>
        /// Log错误信息
        /// </summary>
        /// <param name="data"></param>
        public void ProcessErrorMsg(LoginErrorData data)
        {
            Log.PrintError("登录失败:" + data.errorMsg);
        }

        /// <summary>
        /// logcat测试的时候log一下登录成功的账号
        /// </summary>
        /// <param name="data"></param>
        public void LogcatSuccessData(LoginSuccessData data)
        {
            Log.Print($"{data.username}登录成功");
        }
    }

    //个别方法被监听
    public class GMToolsManager
    {
        public static LoginSuccessData successData;

        /// <summary>
        /// 让钱翻一百倍
        /// </summary>
        /// <param name="data"></param>
        [Subscriber(ThreadMode.Main)]//跑主线程
        public void GetMoreMoney(LoginSuccessData data)
        {
            successData = data;
            successData.money *= 100;
        }
    }
}